]> rtime.felk.cvut.cz Git - socketcan-devel.git/blobdiff - kernel/2.6/drivers/net/can/dev.c
candev: allow SJW user setting for bittiming calculation
[socketcan-devel.git] / kernel / 2.6 / drivers / net / can / dev.c
index ca9e6bc25a8a0fbe6fd74a773db1e75981b3fd6b..59e779be38ee0c9c589b920befe67180145231c7 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
  * Copyright (C) 2006 Andrey Volkov, Varma Electronics
+ * Copyright (C) 2008-2009 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
  */
 
 #include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
-#include <linux/rtnetlink.h>
-#include <linux/can.h>
-#include <linux/can/dev.h>
-
+#include <socketcan/can.h>
+#include <socketcan/can/dev.h>
+#ifndef CONFIG_CAN_DEV_SYSFS
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#error "CAN netlink interface not support by this kernel version"
+#endif
+#include <socketcan/can/netlink.h>
+#include <net/rtnetlink.h>
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
+#error "CAN sysfs interface not support by this kernel version"
+#endif
 #include "sysfs.h"
+#endif
 
-#define MOD_DESC "CAN netdevice library"
+#define MOD_DESC "CAN device driver interface"
 
 MODULE_DESCRIPTION(MOD_DESC);
 MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>, "
-             "Andrey Volkov <avolkov@varma-el.com>");
-
-static int restart_ms;
-
-module_param(restart_ms, int, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(restart_ms, "Restart time after bus-off in ms (default 0)");
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
 
+#ifdef CONFIG_CAN_CALC_BITTIMING
+#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
 
 /*
- * Abstract:
- *   Bit rate calculated with next formula:
- *   bitrate = frq/(brp*(1 + prop_seg+ phase_seg1 + phase_seg2))
- *
- *   This calc function based on work of Florian Hartwich and Armin Bassemi
- *   "The Configuration of the CAN Bit Timing"
- *   (http://www.semiconductors.bosch.de/pdf/CiA99Paper.pdf)
+ * Bit-timing calculation derived from:
  *
- *  Parameters:
- *  [in]
- *    bittime_nsec - expected bit time in nanosecs
+ * 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
  *
- *  [out]
- *    bittime      - calculated time segments, for meaning of
- *                  each field read CAN standard.
+ * Calculates proper bit-timing parameters for a specified bit-rate
+ * and sample-point, which can then be used to set the bit-timing
+ * registers of the CAN controller. You can find more information
+ * in the header file socketcan/can/netlink.h.
  */
-
-#define DEFAULT_MAX_BRP        64U
-#define DEFAULT_MAX_SJW        4U
-
-/* All below values in tq units */
-#define MAX_BITTIME    25U
-#define MIN_BITTIME    8U
-#define MAX_PROP_SEG   8U
-#define MAX_PHASE_SEG1 8U
-#define MAX_PHASE_SEG2 8U
-
-int can_calc_bittime(struct can_priv *can, u32 bitrate,
-                    struct can_bittime_std *bittime)
-{
-       int best_error = -1;    /* Ariphmetic error */
-       int df, best_df = -1;   /* oscillator's tolerance range,
-                                  greater is better */
-       u32 quanta;             /* in tq units */
-       u32 brp, phase_seg1, phase_seg2, sjw, prop_seg;
-       u32 brp_min, brp_max, brp_expected;
-       u64 tmp;
-
-       /* bitrate range [1baud,1MiB/s] */
-       if (bitrate == 0 || bitrate > 1000000UL)
-               return -EINVAL;
-
-       tmp = (u64) can->can_sys_clock * 1000;
-       do_div(tmp, bitrate);
-       brp_expected = (u32) tmp;
-
-       brp_min = brp_expected / (1000 * MAX_BITTIME);
-       if (brp_min == 0)
-               brp_min = 1;
-       if (brp_min > can->max_brp)
-               return -ERANGE;
-
-       brp_max = (brp_expected + 500 * MIN_BITTIME) / (1000 * MIN_BITTIME);
-       if (brp_max == 0)
-               brp_max = 1;
-       if (brp_max > can->max_brp)
-               brp_max = can->max_brp;
-
-       for (brp = brp_min; brp <= brp_max; brp++) {
-               quanta = brp_expected / (brp * 1000);
-               if (quanta < MAX_BITTIME
-                   && quanta * brp * 1000 != brp_expected)
-                       quanta++;
-               if (quanta < MIN_BITTIME || quanta > MAX_BITTIME)
-                       continue;
-
-               phase_seg2 = min((quanta - 3) / 2, MAX_PHASE_SEG2);
-               for (sjw = can->max_sjw; sjw > 0; sjw--) {
-                       for (; phase_seg2 > sjw; phase_seg2--) {
-                               u32 err1, err2;
-                               phase_seg1 =
-                                   phase_seg2 % 2 ? phase_seg2 -
-                                   1 : phase_seg2;
-                               prop_seg = quanta - 1 - phase_seg2 - phase_seg1;
-                               /*
-                                * FIXME: support of longer lines (i.e. bigger
-                                * prop_seg) is more prefered than support of
-                                * cheap oscillators (i.e. bigger
-                                * df/phase_seg1/phase_seg2)
-                                */
-                               if (prop_seg < phase_seg1)
-                                       continue;
-                               if (prop_seg > MAX_PROP_SEG)
-                                       goto next_brp;
-
-                               err1 = phase_seg1 * brp * 500 * 1000 /
-                                   (13 * brp_expected -
-                                    phase_seg2 * brp * 1000);
-                               err2 = sjw * brp * 50 * 1000 / brp_expected;
-
-                               df = min(err1, err2);
-                               if (df >= best_df) {
-                                       unsigned error =
-                                               abs(brp_expected * 10 /
-                                                   (brp * (1 + prop_seg +
-                                                           phase_seg1 +
-                                                           phase_seg2)) -
-                                                   10000);
-
-                                       if (error > 10 || error > best_error)
-                                               continue;
-
-                                       if (error == best_error
-                                           && prop_seg < bittime->prop_seg)
-                                               continue;
-
-                                       best_error = error;
-                                       best_df = df;
-                                       bittime->brp = brp;
-                                       bittime->prop_seg = prop_seg;
-                                       bittime->phase_seg1 = phase_seg1;
-                                       bittime->phase_seg2 = phase_seg2;
-                                       bittime->sjw = sjw;
-                                       bittime->sam =
-                                               (bittime->phase_seg1 > 3);
-                               }
-                       }
-               }
-next_brp:;
+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;
        }
-
-       if (best_error < 0)
-               return -EDOM;
-       return 0;
+       return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
 }
 
-int can_set_bitrate(struct net_device *dev, u32 bitrate)
+static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
 {
        struct can_priv *priv = netdev_priv(dev);
-       int err = -ENOTSUPP;
+       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;
+       }
 
-       if (priv->state != CAN_STATE_STOPPED)
-               return -EBUSY;
+       /* 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 = priv->clock.freq / (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 = priv->clock.freq / (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 (priv->do_set_bittime) {
-               if (priv->do_set_bittime) {
-                       struct can_bittime bittime;
-                       err = can_calc_bittime(priv, bitrate, &bittime.std);
-                       if (err)
-                               goto out;
-                       bittime.type = CAN_BITTIME_STD;
-                       err = priv->do_set_bittime(dev, &bittime);
-                       if (!err) {
-                               priv->bitrate = bitrate;
-                               priv->bittime = bittime;
-                       }
+       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);
                }
        }
-out:
-       return err;
-}
-EXPORT_SYMBOL(can_set_bitrate);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
-static struct net_device_stats *can_get_stats(struct net_device *dev)
-{
-       struct can_priv *priv = netdev_priv(dev);
+       spt = can_update_spt(btc, sampl_pt, best_tseg, &tseg1, &tseg2);
+
+       v64 = (u64)best_brp * 1000000000UL;
+       do_div(v64, priv->clock.freq);
+       bt->tq = (u32)v64;
+       bt->prop_seg = tseg1 / 2;
+       bt->phase_seg1 = tseg1 - bt->prop_seg;
+       bt->phase_seg2 = tseg2;
+
+       /* check for sjw user settings */
+       if (!bt->sjw || !btc->sjw_max)
+               bt->sjw = 1;
+       else {
+               /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
+               if (bt->sjw > btc->sjw_max)
+                       bt->sjw = btc->sjw_max;
+               /* bt->sjw must not be higher than tseg2 */
+               if (tseg2 < bt->sjw)
+                       bt->sjw = tseg2;
+       }
 
-       return &priv->net_stats;
-}
+       bt->brp = best_brp;
+#ifndef CONFIG_CAN_DEV_SYSFS
+       /* real bit-rate */
+       bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));
+       /* real sample point */
+       bt->sample_point = spt;
 #endif
-
-static void can_setup(struct net_device *dev)
+       return 0;
+}
+#else /* !CONFIG_CAN_CALC_BITTIMING */
+static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
 {
-       dev->type = ARPHRD_CAN;
-       dev->mtu = sizeof(struct can_frame);
-       dev->hard_header_len = 0;
-       dev->addr_len = 0;
-       dev->tx_queue_len = 10;
+       dev_err(ND2D(dev), "bit-timing calculation not available\n");
+       return -EINVAL;
+}
+#endif /* CONFIG_CAN_CALC_BITTIMING */
 
-       /* New-style flags. */
-       dev->flags = IFF_NOARP;
-       dev->features = NETIF_F_NO_CSUM;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
-       dev->get_stats = can_get_stats;
-#endif
+
+#ifdef CONFIG_CAN_DEV_SYSFS
+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);
 }
+#endif
 
 /*
- * Function  alloc_candev
- *     Allocates and sets up an CAN device
+ * Checks the validity of the specified bit-timing parameters prop_seg,
+ * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
+ * prescaler value brp. You can find more information in the header
+ * file socketcan/can/netlink.h.
  */
-struct net_device *alloc_candev(int sizeof_priv)
+static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt)
 {
-       struct net_device *dev;
-       struct can_priv *priv;
-
-       dev = alloc_netdev(sizeof_priv, "can%d", can_setup);
-       if (!dev)
-               return NULL;
+       struct can_priv *priv = netdev_priv(dev);
+       const struct can_bittiming_const *btc = priv->bittiming_const;
+       int tseg1, alltseg;
+       u64 brp64;
+
+       if (!priv->bittiming_const)
+               return -ENOTSUPP;
+
+       tseg1 = bt->prop_seg + bt->phase_seg1;
+       if (!bt->sjw)
+               bt->sjw = 1;
+       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 -ERANGE;
 
-       priv = netdev_priv(dev);
+       brp64 = (u64)priv->clock.freq * (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;
 
-       /* Default values can be overwritten by the device driver */
-       priv->restart_ms = restart_ms;
-       priv->bitrate = CAN_BITRATE_UNCONFIGURED;
-       priv->state = CAN_STATE_STOPPED;
-       priv->max_brp = DEFAULT_MAX_BRP;
-       priv->max_sjw = DEFAULT_MAX_SJW;
-       spin_lock_init(&priv->irq_lock);
+       if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
+               return -EINVAL;
 
-       init_timer(&priv->timer);
-       priv->timer.expires = 0;
+       alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
+       bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
+       bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
 
-       return dev;
+       return 0;
 }
-EXPORT_SYMBOL(alloc_candev);
 
-void free_candev(struct net_device *dev)
+int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt)
 {
-       free_netdev(dev);
+       struct can_priv *priv = netdev_priv(dev);
+       int err;
+
+       /* Check if the CAN device has bit-timing parameters */
+       if (priv->bittiming_const) {
+
+               /* Non-expert mode? Check if the bitrate has been pre-defined */
+               if (!bt->tq)
+                       /* Determine bit-timing parameters */
+                       err = can_calc_bittiming(dev, bt);
+               else
+                       /* Check bit-timing params and calculate proper brp */
+                       err = can_fixup_bittiming(dev, bt);
+               if (err)
+                       return err;
+       }
+
+       return 0;
 }
-EXPORT_SYMBOL(free_candev);
 
 /*
  * Local echo of CAN messages
@@ -266,32 +274,41 @@ EXPORT_SYMBOL(free_candev);
  * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
  * to perform the echo as a fallback solution.
  */
-
-void can_flush_echo_skb(struct net_device *dev)
+static void can_flush_echo_skb(struct net_device *dev)
 {
        struct can_priv *priv = netdev_priv(dev);
-#ifdef FIXME
-       struct net_device_stats *stats = dev->get_stats(dev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+       struct net_device_stats *stats = can_get_stats(dev);
+#else
+       struct net_device_stats *stats = &dev->stats;
 #endif
        int i;
 
-       for (i = 0; i < CAN_ECHO_SKB_MAX; i++) {
+       for (i = 0; i < priv->echo_skb_max; i++) {
                if (priv->echo_skb[i]) {
                        kfree_skb(priv->echo_skb[i]);
                        priv->echo_skb[i] = NULL;
-#ifdef FIXME
                        stats->tx_dropped++;
                        stats->tx_aborted_errors++;
-#endif
                }
        }
 }
 
-void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
+/*
+ * 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. The driver must protect access to
+ * priv->echo_skb, if necessary.
+ */
+void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
+                     unsigned int idx)
 {
        struct can_priv *priv = netdev_priv(dev);
 
-       /* set flag whether this packet has to be looped back */
+       BUG_ON(idx >= priv->echo_skb_max);
+
+       /* check flag whether this packet has to be looped back */
        if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) {
                kfree_skb(skb);
                return;
@@ -313,7 +330,7 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
                skb->sk = srcsk;
 
                /* make settings for echo to reduce code in irq context */
-               skb->protocol = htons(ETH_P_CAN);
+               skb->protocol = __constant_htons(ETH_P_CAN);
                skb->pkt_type = PACKET_BROADCAST;
                skb->ip_summed = CHECKSUM_UNNECESSARY;
                skb->dev = dev;
@@ -322,165 +339,541 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
                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__);
+               dev_err(ND2D(dev), "%s: BUG! echo_skb is occupied!\n",
+                       __func__);
                kfree_skb(skb);
        }
 }
-EXPORT_SYMBOL(can_put_echo_skb);
+EXPORT_SYMBOL_GPL(can_put_echo_skb);
 
-void can_get_echo_skb(struct net_device *dev, int idx)
+/*
+ * 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. The driver must protect
+ * access to priv->echo_skb, if necessary.
+ */
+void can_get_echo_skb(struct net_device *dev, unsigned int idx)
 {
        struct can_priv *priv = netdev_priv(dev);
 
-       if ((dev->flags & IFF_ECHO) && priv->echo_skb[idx]) {
+       BUG_ON(idx >= priv->echo_skb_max);
+
+       if (priv->echo_skb[idx]) {
                netif_rx(priv->echo_skb[idx]);
                priv->echo_skb[idx] = NULL;
        }
 }
-EXPORT_SYMBOL(can_get_echo_skb);
+EXPORT_SYMBOL_GPL(can_get_echo_skb);
 
 /*
- * CAN bus-off handling
- * FIXME: we need some synchronization
+  * Remove the skb from the stack and free it.
+  *
+  * The function is typically called when TX failed.
+  */
+void can_free_echo_skb(struct net_device *dev, unsigned int idx)
+{
+       struct can_priv *priv = netdev_priv(dev);
+
+       BUG_ON(idx >= priv->echo_skb_max);
+
+       if (priv->echo_skb[idx]) {
+               kfree_skb(priv->echo_skb[idx]);
+               priv->echo_skb[idx] = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(can_free_echo_skb);
+
+/*
+ * CAN device restart for bus-off recovery
  */
-int can_restart_now(struct net_device *dev)
+void can_restart(unsigned long data)
 {
+       struct net_device *dev = (struct net_device *)data;
        struct can_priv *priv = netdev_priv(dev);
-       struct net_device_stats *stats = dev->get_stats(dev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+       struct net_device_stats *stats = can_get_stats(dev);
+#else
+       struct net_device_stats *stats = &dev->stats;
+#endif
        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 */
-       }
+       BUG_ON(netif_carrier_ok(dev));
 
+       /*
+        * No synchronization needed because the device is bus-off and
+        * no messages can come in or go out.
+        */
        can_flush_echo_skb(dev);
 
-       err = priv->do_set_mode(dev, CAN_MODE_START);
-       if (err)
-               return err;
-
-       netif_carrier_on(dev);
-
-       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;
+       skb = alloc_can_err_skb(dev, &cf);
+       if (skb == NULL) {
+               err = -ENOMEM;
+               goto restart;
+       }
+       cf->can_id |= CAN_ERR_RESTARTED;
 
        netif_rx(skb);
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
        dev->last_rx = jiffies;
+#endif
        stats->rx_packets++;
        stats->rx_bytes += cf->can_dlc;
 
-       return 0;
+restart:
+       dev_dbg(ND2D(dev), "restarted\n");
+       priv->can_stats.restarts++;
+
+       /* Now restart the device */
+       err = priv->do_set_mode(dev, CAN_MODE_START);
+
+       netif_carrier_on(dev);
+       if (err)
+               dev_err(ND2D(dev), "Error %d during restart", err);
 }
 
-static void can_restart_after(unsigned long data)
+int can_restart_now(struct net_device *dev)
 {
-       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);
+       /*
+        * A manual restart is only permitted if automatic restart is
+        * disabled and the device is in the bus-off state
+        */
+       if (priv->restart_ms)
+               return -EINVAL;
+       if (priv->state != CAN_STATE_BUS_OFF)
+               return -EBUSY;
+
+       /* Runs as soon as possible in the timer context */
+       mod_timer(&priv->restart_timer, jiffies);
+
+       return 0;
 }
 
+/*
+ * 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);
+       priv->can_stats.bus_off++;
 
-       if (priv->restart_ms > 0 && !priv->timer.expires) {
+       if (priv->restart_ms)
+               mod_timer(&priv->restart_timer,
+                         jiffies + (priv->restart_ms * HZ) / 1000);
+}
+EXPORT_SYMBOL_GPL(can_bus_off);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+struct net_device_stats *can_get_stats(struct net_device *dev)
+{
+       struct can_priv *priv = netdev_priv(dev);
+
+       return &priv->net_stats;
+}
+EXPORT_SYMBOL_GPL(can_get_stats);
+#endif
 
-               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);
+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;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+       dev->get_stats = can_get_stats;
+#endif
+}
+
+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));
+       if (unlikely(!skb))
+               return NULL;
+
+       skb->protocol = __constant_htons(ETH_P_CAN);
+       skb->pkt_type = PACKET_BROADCAST;
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+       memset(*cf, 0, sizeof(struct can_frame));
+
+       return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_can_skb);
+
+struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
+{
+       struct sk_buff *skb;
+
+       skb = alloc_can_skb(dev, cf);
+       if (unlikely(!skb))
+               return NULL;
+
+       (*cf)->can_id = CAN_ERR_FLAG;
+       (*cf)->can_dlc = CAN_ERR_DLC;
+
+       return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_can_err_skb);
+
+/*
+ * Allocate and setup space for the CAN network device
+ */
+struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
+{
+       struct net_device *dev;
+       struct can_priv *priv;
+       int size;
+
+       if (echo_skb_max)
+               size = ALIGN(sizeof_priv, sizeof(struct sk_buff *)) +
+                       echo_skb_max * sizeof(struct sk_buff *);
+       else
+               size = sizeof_priv;
+
+       dev = alloc_netdev(size, "can%d", can_setup);
+       if (!dev)
+               return NULL;
+
+       priv = netdev_priv(dev);
+
+       if (echo_skb_max) {
+               priv->echo_skb_max = echo_skb_max;
+               priv->echo_skb = (void *)priv +
+                       ALIGN(sizeof_priv, sizeof(struct sk_buff *));
        }
+
+       priv->state = CAN_STATE_STOPPED;
+
+       init_timer(&priv->restart_timer);
+
+       return dev;
+}
+EXPORT_SYMBOL_GPL(alloc_candev);
+
+/*
+ * Free space of the CAN network device
+ */
+void free_candev(struct net_device *dev)
+{
+       free_netdev(dev);
 }
-EXPORT_SYMBOL(can_bus_off);
+EXPORT_SYMBOL_GPL(free_candev);
 
-void can_close_cleanup(struct net_device *dev)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+static inline void setup_timer(struct timer_list * timer,
+                               void (*function)(unsigned long),
+                               unsigned long data)
+{
+       timer->function = function;
+       timer->data = data;
+       init_timer(timer);
+}
+#endif
+
+/*
+ * Common open function when the device gets opened.
+ *
+ * This function should be called in the open function of the device
+ * driver.
+ */
+int open_candev(struct net_device *dev)
 {
        struct can_priv *priv = netdev_priv(dev);
+#ifdef CONFIG_CAN_DEV_SYSFS
+       int err;
+#endif
 
-       if (priv->timer.expires) {
-               del_timer(&priv->timer);
-               priv->timer.expires = 0;
+       if (!priv->bittiming.tq && !priv->bittiming.bitrate) {
+               dev_err(ND2D(dev), "bit-timing not yet defined\n");
+               return -EINVAL;
        }
 
+#ifdef CONFIG_CAN_DEV_SYSFS
+       err = can_get_bittiming(dev, &priv->bittiming);
+       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;
+       }
+#endif
+
+       /* Switch carrier on if device was stopped while in bus-off state */
+       if (!netif_carrier_ok(dev))
+               netif_carrier_on(dev);
+
+       setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(open_candev);
+
+/*
+ * Common close function for cleanup before the device gets closed.
+ *
+ * This function should be called in the close function of the device
+ * driver.
+ */
+void close_candev(struct net_device *dev)
+{
+       struct can_priv *priv = netdev_priv(dev);
+
+       if (del_timer_sync(&priv->restart_timer))
+               dev_put(dev);
        can_flush_echo_skb(dev);
 }
-EXPORT_SYMBOL(can_close_cleanup);
+EXPORT_SYMBOL_GPL(close_candev);
+
+#ifndef CONFIG_CAN_DEV_SYSFS
+/*
+ * CAN netlink interface
+ */
+static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
+       [IFLA_CAN_STATE]        = { .type = NLA_U32 },
+       [IFLA_CAN_CTRLMODE]     = { .len = sizeof(struct can_ctrlmode) },
+       [IFLA_CAN_RESTART_MS]   = { .type = NLA_U32 },
+       [IFLA_CAN_RESTART]      = { .type = NLA_U32 },
+       [IFLA_CAN_BITTIMING]    = { .len = sizeof(struct can_bittiming) },
+       [IFLA_CAN_BITTIMING_CONST]
+                               = { .len = sizeof(struct can_bittiming_const) },
+       [IFLA_CAN_CLOCK]        = { .len = sizeof(struct can_clock) },
+       [IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) },
+};
 
-static int can_netdev_notifier_call(struct notifier_block *nb,
-                                   unsigned long state,
-                                   void *ndev)
+static int can_changelink(struct net_device *dev,
+                         struct nlattr *tb[], struct nlattr *data[])
 {
-       struct net_device *dev = ndev;
-       struct can_priv *priv;
+       struct can_priv *priv = netdev_priv(dev);
+       int err;
 
-       if (dev->type != ARPHRD_CAN)
-               return 0;
+       /* We need synchronization with dev->stop() */
+       ASSERT_RTNL();
 
-       priv = netdev_priv(dev);
+       if (data[IFLA_CAN_CTRLMODE]) {
+               struct can_ctrlmode *cm;
 
-       /* software CAN devices like 'vcan' do not have private data */
-       if (!priv)
-               return 0;
-
-       switch (state) {
-       case NETDEV_REGISTER:
-               /* set default bit timing */
-               if (priv->do_set_bittime &&
-                   priv->bitrate == CAN_BITRATE_UNCONFIGURED) {
-                       if (can_set_bitrate(dev, CAN_BITRATE_DEFAULT))
-                               dev_err(ND2D(dev), "failed to set bitrate\n");
+               /* Do not allow changing controller mode while running */
+               if (dev->flags & IFF_UP)
+                       return -EBUSY;
+               cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+               if (cm->flags & ~priv->ctrlmode_supported)
+                       return -EOPNOTSUPP;
+               priv->ctrlmode &= ~cm->mask;
+               priv->ctrlmode |= cm->flags;
+       }
+
+       if (data[IFLA_CAN_BITTIMING]) {
+               struct can_bittiming bt;
+
+               /* Do not allow changing bittiming while running */
+               if (dev->flags & IFF_UP)
+                       return -EBUSY;
+               memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
+               if ((!bt.bitrate && !bt.tq) || (bt.bitrate && bt.tq))
+                       return -EINVAL;
+               err = can_get_bittiming(dev, &bt);
+               if (err)
+                       return err;
+               memcpy(&priv->bittiming, &bt, sizeof(bt));
+
+               if (priv->do_set_bittiming) {
+                       /* Finally, set the bit-timing registers */
+                       err = priv->do_set_bittiming(dev);
+                       if (err)
+                               return err;
                }
-#ifdef CONFIG_SYSFS
-               can_create_sysfs(dev);
-#endif
-               break;
-       case NETDEV_UNREGISTER:
-#ifdef CONFIG_SYSFS
-               can_remove_sysfs(dev);
-#endif
-               break;
        }
+
+       if (data[IFLA_CAN_RESTART_MS]) {
+               /* Do not allow changing restart delay while running */
+               if (dev->flags & IFF_UP)
+                       return -EBUSY;
+               priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]);
+       }
+
+       if (data[IFLA_CAN_RESTART]) {
+               /* Do not allow a restart while not running */
+               if (!(dev->flags & IFF_UP))
+                       return -EINVAL;
+               err = can_restart_now(dev);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static size_t can_get_size(const struct net_device *dev)
+{
+       struct can_priv *priv = netdev_priv(dev);
+       size_t size;
+
+       size = nla_total_size(sizeof(u32));   /* IFLA_CAN_STATE */
+       size += sizeof(struct can_ctrlmode);  /* IFLA_CAN_CTRLMODE */
+       size += nla_total_size(sizeof(u32));  /* IFLA_CAN_RESTART_MS */
+       size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */
+       size += sizeof(struct can_clock);     /* IFLA_CAN_CLOCK */
+       if (priv->do_get_berr_counter)        /* IFLA_CAN_BERR_COUNTER */
+               size += sizeof(struct can_berr_counter);
+       if (priv->bittiming_const)            /* IFLA_CAN_BITTIMING_CONST */
+               size += sizeof(struct can_bittiming_const);
+
+       return size;
+}
+
+static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct can_priv *priv = netdev_priv(dev);
+       struct can_ctrlmode cm = {.flags = priv->ctrlmode};
+       struct can_berr_counter bec;
+       enum can_state state = priv->state;
+
+       if (priv->do_get_state)
+               priv->do_get_state(dev, &state);
+       NLA_PUT_U32(skb, IFLA_CAN_STATE, state);
+       NLA_PUT(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm);
+       NLA_PUT_U32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms);
+       NLA_PUT(skb, IFLA_CAN_BITTIMING,
+               sizeof(priv->bittiming), &priv->bittiming);
+       NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock);
+       if (priv->do_get_berr_counter && !priv->do_get_berr_counter(dev, &bec))
+               NLA_PUT(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec);
+       if (priv->bittiming_const)
+               NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST,
+                       sizeof(*priv->bittiming_const), priv->bittiming_const);
+
        return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
 }
 
-static struct notifier_block can_netdev_notifier = {
-       .notifier_call = can_netdev_notifier_call,
+static size_t can_get_xstats_size(const struct net_device *dev)
+{
+       return sizeof(struct can_device_stats);
+}
+
+static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct can_priv *priv = netdev_priv(dev);
+
+       NLA_PUT(skb, IFLA_INFO_XSTATS,
+               sizeof(priv->can_stats), &priv->can_stats);
+
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+static int can_newlink(struct net_device *dev,
+                      struct nlattr *tb[], struct nlattr *data[])
+#else
+static int can_newlink(struct net *src_net, struct net_device *dev,
+                      struct nlattr *tb[], struct nlattr *data[])
+#endif
+{
+       return -EOPNOTSUPP;
+}
+
+static struct rtnl_link_ops can_link_ops __read_mostly = {
+       .kind           = "can",
+       .maxtype        = IFLA_CAN_MAX,
+       .policy         = can_policy,
+       .setup          = can_setup,
+       .newlink        = can_newlink,
+       .changelink     = can_changelink,
+       .get_size       = can_get_size,
+       .fill_info      = can_fill_info,
+       .get_xstats_size = can_get_xstats_size,
+       .fill_xstats    = can_fill_xstats,
 };
 
+#endif /* !CONFIG_CAN_DEV_SYSFS */
+
+/*
+ * Register the CAN network device
+ */
+int register_candev(struct net_device *dev)
+{
+#ifdef CONFIG_CAN_DEV_SYSFS
+       int err;
+
+       err = register_netdev(dev);
+       if (!err)
+               can_create_sysfs(dev);
+
+       return err;
+#else
+       dev->rtnl_link_ops = &can_link_ops;
+       return register_netdev(dev);
+#endif
+}
+EXPORT_SYMBOL_GPL(register_candev);
+
+/*
+ * Unregister the CAN network device
+ */
+void unregister_candev(struct net_device *dev)
+{
+#ifdef CONFIG_CAN_DEV_SYSFS
+       can_remove_sysfs(dev);
+#endif
+       unregister_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(unregister_candev);
+
 static __init int can_dev_init(void)
 {
-       printk(KERN_INFO MOD_DESC "\n");
+#ifndef CONFIG_CAN_DEV_SYSFS
+       int err;
+
+       err = rtnl_link_register(&can_link_ops);
+       if (!err)
+               printk(KERN_INFO MOD_DESC "\n");
 
-       return register_netdevice_notifier(&can_netdev_notifier);
+       return err;
+#else
+       printk(KERN_INFO MOD_DESC " using the deprecated SYSFS interface\n");
+
+       return 0;
+#endif
 }
 module_init(can_dev_init);
 
 static __exit void can_dev_exit(void)
 {
-       unregister_netdevice_notifier(&can_netdev_notifier);
+#ifndef CONFIG_CAN_DEV_SYSFS
+       rtnl_link_unregister(&can_link_ops);
+#endif
 }
 module_exit(can_dev_exit);
+
+#ifndef CONFIG_CAN_DEV_SYSFS
+MODULE_ALIAS_RTNL_LINK("can");
+#endif