*
* 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_REV "20080620"
+#define MOD_DESC "CAN device driver interface"
-MODULE_DESCRIPTION(MOD_DESC " (rev " MOD_REV ")");
+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
* 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;
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;
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 " (rev " MOD_REV ")\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