---
include/linux/can.h | 111 +++++
- include/linux/can/core.h | 78 +++
+ include/linux/can/core.h | 64 +++
include/linux/can/error.h | 93 ++++
net/Kconfig | 1
net/Makefile | 1
- net/can/Kconfig | 25 +
+ net/can/Kconfig | 17
net/can/Makefile | 6
- net/can/af_can.c | 975 ++++++++++++++++++++++++++++++++++++++++++++++
- net/can/af_can.h | 120 +++++
- net/can/proc.c | 532 +++++++++++++++++++++++++
- 10 files changed, 1942 insertions(+)
+ net/can/af_can.c | 861 ++++++++++++++++++++++++++++++++++++++++++++++
+ net/can/af_can.h | 122 ++++++
+ net/can/proc.c | 533 ++++++++++++++++++++++++++++
+ 10 files changed, 1809 insertions(+)
Index: net-2.6.25/include/linux/can.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/include/linux/can.h 2007-11-14 13:04:49.000000000 +0100
++++ net-2.6.25/include/linux/can.h 2007-11-16 11:11:50.000000000 +0100
@@ -0,0 +1,111 @@
+/*
+ * linux/can.h
Index: net-2.6.25/include/linux/can/core.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/include/linux/can/core.h 2007-11-14 13:04:49.000000000 +0100
-@@ -0,0 +1,78 @@
++++ net-2.6.25/include/linux/can/core.h 2007-11-16 14:38:25.000000000 +0100
+@@ -0,0 +1,64 @@
+/*
+ * linux/can/core.h
+ *
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
-+#define CAN_VERSION "20071027"
++#define CAN_VERSION "20071116"
+
+/* increment this number each time you change some user-space interface */
+#define CAN_ABI_VERSION "8"
+
+extern int can_send(struct sk_buff *skb, int loop);
+
-+#ifdef CONFIG_CAN_DEBUG_CORE
-+extern void can_debug_skb(struct sk_buff *skb);
-+extern void can_debug_cframe(const char *msg, struct can_frame *cframe);
-+#define DBG(fmt, args...) (DBG_VAR & 1 ? printk( \
-+ KERN_DEBUG DBG_PREFIX ": %s: " fmt, \
-+ __func__, ##args) : 0)
-+#define DBG_FRAME(fmt, cf) (DBG_VAR & 2 ? can_debug_cframe(fmt, cf) : 0)
-+#define DBG_SKB(skb) (DBG_VAR & 4 ? can_debug_skb(skb) : 0)
-+#else
-+#define DBG(fmt, args...)
-+#define DBG_FRAME(fmt, cf)
-+#define DBG_SKB(skb)
-+#endif
-+
+#endif /* CAN_CORE_H */
Index: net-2.6.25/net/Kconfig
===================================================================
---- net-2.6.25.orig/net/Kconfig 2007-11-14 13:04:26.000000000 +0100
-+++ net-2.6.25/net/Kconfig 2007-11-14 13:04:49.000000000 +0100
+--- net-2.6.25.orig/net/Kconfig 2007-11-15 21:47:52.000000000 +0100
++++ net-2.6.25/net/Kconfig 2007-11-16 11:11:50.000000000 +0100
@@ -218,6 +218,7 @@
endmenu
source "net/rxrpc/Kconfig"
Index: net-2.6.25/net/Makefile
===================================================================
---- net-2.6.25.orig/net/Makefile 2007-11-14 13:04:26.000000000 +0100
-+++ net-2.6.25/net/Makefile 2007-11-14 13:04:49.000000000 +0100
+--- net-2.6.25.orig/net/Makefile 2007-11-15 21:47:52.000000000 +0100
++++ net-2.6.25/net/Makefile 2007-11-16 11:11:51.000000000 +0100
@@ -34,6 +34,7 @@
obj-$(CONFIG_NETROM) += netrom/
obj-$(CONFIG_ROSE) += rose/
Index: net-2.6.25/net/can/Kconfig
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/net/can/Kconfig 2007-11-14 13:04:49.000000000 +0100
-@@ -0,0 +1,25 @@
++++ net-2.6.25/net/can/Kconfig 2007-11-16 14:34:20.000000000 +0100
+@@ -0,0 +1,17 @@
+#
+# Controller Area Network (CAN) network layer core configuration
+#
+
+ If you want CAN support you should say Y here and also to the
+ specific driver for your controller(s) below.
-+
-+config CAN_DEBUG_CORE
-+ bool "CAN Core debugging messages"
-+ depends on CAN
-+ ---help---
-+ Say Y here if you want the CAN core to produce a bunch of debug
-+ messages. Select this if you are having a problem with CAN
-+ support and want to see more of what is going on.
Index: net-2.6.25/net/can/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/net/can/Makefile 2007-11-14 13:04:49.000000000 +0100
++++ net-2.6.25/net/can/Makefile 2007-11-16 14:25:56.000000000 +0100
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux Controller Area Network core.
Index: net-2.6.25/net/can/af_can.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/net/can/af_can.c 2007-11-14 13:04:49.000000000 +0100
-@@ -0,0 +1,975 @@
++++ net-2.6.25/net/can/af_can.c 2007-11-16 14:27:26.000000000 +0100
+@@ -0,0 +1,861 @@
+/*
+ * af_can.c - Protocol family CAN core module
+ * (used by different CAN protocol modules)
+module_param(stats_timer, int, S_IRUGO);
+MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)");
+
-+#ifdef CONFIG_CAN_DEBUG_CORE
-+#define DBG_PREFIX "can"
-+#define DBG_VAR can_debug
-+static int can_debug __read_mostly;
-+module_param_named(debug, can_debug, int, S_IRUGO);
-+MODULE_PARM_DESC(debug, "debug print mask: 1:debug, 2:frames, 4:skbs");
-+#endif
-+
-+HLIST_HEAD(rx_dev_list);
-+static struct dev_rcv_lists rx_alldev_list;
-+static DEFINE_SPINLOCK(rcv_lists_lock);
++HLIST_HEAD(can_rx_dev_list);
++static struct dev_rcv_lists can_rx_alldev_list;
++static DEFINE_SPINLOCK(can_rcvlists_lock);
+
+static struct kmem_cache *rcv_cache __read_mostly;
+
+static struct can_proto *proto_tab[CAN_NPROTO] __read_mostly;
+static DEFINE_SPINLOCK(proto_tab_lock);
+
-+struct timer_list stattimer; /* timer for statistics update */
-+struct s_stats stats; /* packet statistics */
-+struct s_pstats pstats; /* receive list statistics */
++struct timer_list can_stattimer; /* timer for statistics update */
++struct s_stats can_stats; /* packet statistics */
++struct s_pstats can_pstats; /* receive list statistics */
+
+/*
+ * af_can socket functions
+
+static void can_sock_destruct(struct sock *sk)
+{
-+ DBG("called for sock %p\n", sk);
-+
+ skb_queue_purge(&sk->sk_receive_queue);
+}
+
+ char module_name[sizeof("can-proto-000")];
+ int err = 0;
+
-+ DBG("socket %p, type %d, proto %d\n", sock, sock->type, protocol);
-+
+ sock->state = SS_UNCONNECTED;
+
+ if (protocol < 0 || protocol >= CAN_NPROTO)
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+
-+ DBG("looking up proto %d in proto_tab[]\n", protocol);
-+
+ /* try to load protocol module, when CONFIG_KMOD is defined */
+ if (!proto_tab[protocol]) {
+ sprintf(module_name, "can-proto-%d", protocol);
+ if (err == -ENOSYS) {
+ if (printk_ratelimit())
+ printk(KERN_INFO "can: request_module(%s)"
-+ " not implemented.\n", module_name);
++ " not implemented.\n", module_name);
+ } else if (err) {
+ if (printk_ratelimit())
+ printk(KERN_ERR "can: request_module(%s)"
+ sock_init_data(sock, sk);
+ sk->sk_destruct = can_sock_destruct;
+
-+ DBG("created sock: %p\n", sk);
-+
+ if (sk->sk_prot->init)
+ err = sk->sk_prot->init(sk);
+
+ err = net_xmit_errno(err);
+
+ /* update statistics */
-+ stats.tx_frames++;
-+ stats.tx_frames_delta++;
++ can_stats.tx_frames++;
++ can_stats.tx_frames_delta++;
+
+ return err;
+}
+ * cursor variable n to decide if a match was found.
+ */
+
-+ hlist_for_each_entry_rcu(d, n, &rx_dev_list, list) {
++ hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
+ if (d->dev == dev)
+ break;
+ }
+
+ /* insert new receiver (dev,canid,mask) -> (func,data) */
+
-+ DBG("dev %p (%s), id %03X, mask %03X, callback %p, data %p, "
-+ "ident %s\n", dev, DNAME(dev), can_id, mask, func, data, ident);
-+
+ r = kmem_cache_alloc(rcv_cache, GFP_KERNEL);
+ if (!r)
+ return -ENOMEM;
+
-+ spin_lock(&rcv_lists_lock);
++ spin_lock(&can_rcvlists_lock);
+
+ d = find_dev_rcv_lists(dev);
+ if (d) {
+ hlist_add_head_rcu(&r->list, rl);
+ d->entries++;
+
-+ pstats.rcv_entries++;
-+ if (pstats.rcv_entries_max < pstats.rcv_entries)
-+ pstats.rcv_entries_max = pstats.rcv_entries;
++ can_pstats.rcv_entries++;
++ if (can_pstats.rcv_entries_max < can_pstats.rcv_entries)
++ can_pstats.rcv_entries_max = can_pstats.rcv_entries;
+ } else {
-+ DBG("receive list not found for dev %s, id %03X, mask %03X\n",
-+ DNAME(dev), can_id, mask);
+ kmem_cache_free(rcv_cache, r);
+ err = -ENODEV;
+ }
+
-+ spin_unlock(&rcv_lists_lock);
++ spin_unlock(&can_rcvlists_lock);
+
+ return err;
+}
+{
+ struct dev_rcv_lists *d = container_of(rp, struct dev_rcv_lists, rcu);
+
-+ DBG("removing dev_rcv_list at %p\n", d);
+ kfree(d);
+}
+
+{
+ struct receiver *r = container_of(rp, struct receiver, rcu);
+
-+ DBG("removing receiver at %p\n", r);
+ kmem_cache_free(rcv_cache, r);
+}
+
+ struct hlist_node *next;
+ struct dev_rcv_lists *d;
+
-+ DBG("dev %p (%s), id %03X, mask %03X, callback %p, data %p\n",
-+ dev, DNAME(dev), can_id, mask, func, data);
-+
-+ spin_lock(&rcv_lists_lock);
++ spin_lock(&can_rcvlists_lock);
+
+ d = find_dev_rcv_lists(dev);
+ if (!d) {
+ hlist_del_rcu(&r->list);
+ d->entries--;
+
-+ if (pstats.rcv_entries > 0)
-+ pstats.rcv_entries--;
++ if (can_pstats.rcv_entries > 0)
++ can_pstats.rcv_entries--;
+
+ /* remove device structure requested by NETDEV_UNREGISTER */
-+ if (d->remove_on_zero_entries && !d->entries) {
-+ DBG("removing dev_rcv_list for %s on zero entries\n",
-+ dev->name);
++ if (d->remove_on_zero_entries && !d->entries)
+ hlist_del_rcu(&d->list);
-+ } else
++ else
+ d = NULL;
+
+ out:
-+ spin_unlock(&rcv_lists_lock);
++ spin_unlock(&can_rcvlists_lock);
+
+ /* schedule the receiver item for deletion */
+ if (r)
+{
+ struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
+
-+ DBG("skbuff %p cloned to %p\n", skb, clone);
+ if (clone) {
+ clone->sk = skb->sk;
+ r->func(clone, r->data);
+ /* check for error frame entries only */
+ hlist_for_each_entry_rcu(r, n, &d->rx[RX_ERR], list) {
+ if (can_id & r->mask) {
-+ DBG("match on rx_err skbuff %p\n", skb);
+ deliver(skb, r);
+ matches++;
+ }
+
+ /* check for unfiltered entries */
+ hlist_for_each_entry_rcu(r, n, &d->rx[RX_ALL], list) {
-+ DBG("match on rx_all skbuff %p\n", skb);
+ deliver(skb, r);
+ matches++;
+ }
+ /* check for can_id/mask entries */
+ hlist_for_each_entry_rcu(r, n, &d->rx[RX_FIL], list) {
+ if ((can_id & r->mask) == r->can_id) {
-+ DBG("match on rx_fil skbuff %p\n", skb);
+ deliver(skb, r);
+ matches++;
+ }
+ /* check for inverted can_id/mask entries */
+ hlist_for_each_entry_rcu(r, n, &d->rx[RX_INV], list) {
+ if ((can_id & r->mask) != r->can_id) {
-+ DBG("match on rx_inv skbuff %p\n", skb);
+ deliver(skb, r);
+ matches++;
+ }
+ if (can_id & CAN_EFF_FLAG) {
+ hlist_for_each_entry_rcu(r, n, &d->rx[RX_EFF], list) {
+ if (r->can_id == can_id) {
-+ DBG("match on rx_eff skbuff %p\n", skb);
+ deliver(skb, r);
+ matches++;
+ }
+ } else {
+ can_id &= CAN_SFF_MASK;
+ hlist_for_each_entry_rcu(r, n, &d->rx_sff[can_id], list) {
-+ DBG("match on rx_sff skbuff %p\n", skb);
+ deliver(skb, r);
+ matches++;
+ }
+ struct dev_rcv_lists *d;
+ int matches;
+
-+ DBG("received skbuff on device %s, ptype %04x\n",
-+ dev->name, ntohs(pt->type));
-+ DBG_SKB(skb);
-+ DBG_FRAME("can: can_rcv: received CAN frame",
-+ (struct can_frame *)skb->data);
-+
+ if (dev->type != ARPHRD_CAN || dev->nd_net != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ /* update statistics */
-+ stats.rx_frames++;
-+ stats.rx_frames_delta++;
++ can_stats.rx_frames++;
++ can_stats.rx_frames_delta++;
+
+ rcu_read_lock();
+
+ /* deliver the packet to sockets listening on all devices */
-+ matches = can_rcv_filter(&rx_alldev_list, skb);
++ matches = can_rcv_filter(&can_rx_alldev_list, skb);
+
+ /* find receive list for this device */
+ d = find_dev_rcv_lists(dev);
+ rcu_read_unlock();
+
+ /* free the skbuff allocated by the netdevice driver */
-+ DBG("freeing skbuff %p\n", skb);
+ kfree_skb(skb);
+
+ if (matches > 0) {
-+ stats.matches++;
-+ stats.matches_delta++;
++ can_stats.matches++;
++ can_stats.matches_delta++;
+ }
+
+ return 0;
+ struct net_device *dev = (struct net_device *)data;
+ struct dev_rcv_lists *d;
+
-+ DBG("msg %ld for dev %p (%s idx %d)\n",
-+ msg, dev, dev->name, dev->ifindex);
-+
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
+ * explicit initialization.
+ */
+
-+ DBG("creating new dev_rcv_lists for %s\n", dev->name);
-+
+ d = kzalloc(sizeof(*d), GFP_KERNEL);
+ if (!d) {
+ printk(KERN_ERR
+ }
+ d->dev = dev;
+
-+ spin_lock(&rcv_lists_lock);
-+ hlist_add_head_rcu(&d->list, &rx_dev_list);
-+ spin_unlock(&rcv_lists_lock);
++ spin_lock(&can_rcvlists_lock);
++ hlist_add_head_rcu(&d->list, &can_rx_dev_list);
++ spin_unlock(&can_rcvlists_lock);
+
+ break;
+
+ case NETDEV_UNREGISTER:
-+ spin_lock(&rcv_lists_lock);
++ spin_lock(&can_rcvlists_lock);
+
+ d = find_dev_rcv_lists(dev);
+ if (d) {
-+ DBG("remove dev_rcv_list for %s (%d entries)\n",
-+ dev->name, d->entries);
-+
+ if (d->entries) {
+ d->remove_on_zero_entries = 1;
+ d = NULL;
+ printk(KERN_ERR "can: notifier: receive list not "
+ "found for dev %s\n", dev->name);
+
-+ spin_unlock(&rcv_lists_lock);
++ spin_unlock(&can_rcvlists_lock);
+
+ if (d)
+ call_rcu(&d->rcu, can_rx_delete_device);
+}
+
+/*
-+ * af_can debugging stuff
-+ */
-+
-+#ifdef CONFIG_CAN_DEBUG_CORE
-+
-+/**
-+ * can_debug_cframe - print CAN frame
-+ * @msg: pointer to message printed before the given CAN frame
-+ * @cf: pointer to CAN frame
-+ */
-+void can_debug_cframe(const char *msg, struct can_frame *cf)
-+{
-+ char idbuf[12];
-+ char hexbuf[28];
-+ int dlc;
-+
-+ dlc = cf->can_dlc;
-+ if (dlc > 8)
-+ dlc = 8;
-+
-+ if (cf->can_id & CAN_EFF_FLAG)
-+ sprintf(idbuf, "<%08X>", cf->can_id & CAN_EFF_MASK);
-+ else
-+ sprintf(idbuf, "<%03X>", cf->can_id & CAN_SFF_MASK);
-+
-+ if (cf->can_id & CAN_RTR_FLAG)
-+ sprintf(hexbuf, "(RTR)");
-+ else
-+ hex_dump_to_buffer(cf->data, dlc, 16, 1, hexbuf, 28, 0);
-+
-+ printk(KERN_DEBUG "%s: %s [%d] %s\n", msg, idbuf, dlc, hexbuf);
-+}
-+EXPORT_SYMBOL(can_debug_cframe);
-+
-+/**
-+ * can_debug_skb - print socket buffer content to kernel log
-+ * @skb: pointer to socket buffer
-+ */
-+void can_debug_skb(struct sk_buff *skb)
-+{
-+ printk(KERN_DEBUG " skbuff at %p, dev: %d, proto: %04x\n"
-+ KERN_DEBUG " users: %d, dataref: %d, nr_frags: %d, "
-+ "h,d,t,e,l: %p %+d %+d %+d, %d\n",
-+ skb, skb->dev ? skb->dev->ifindex : -1,
-+ ntohs(skb->protocol),
-+ atomic_read(&skb->users),
-+ atomic_read(&(skb_shinfo(skb)->dataref)),
-+ skb_shinfo(skb)->nr_frags,
-+ skb->head, skb->data - skb->head,
-+ skb->tail - skb->head, skb->end - skb->head, skb->len);
-+
-+ print_hex_dump(KERN_DEBUG, "skb_head: ", DUMP_PREFIX_NONE,
-+ 16, 1, skb->head, skb->end - skb->head, 0);
-+}
-+EXPORT_SYMBOL(can_debug_skb);
-+
-+#endif
-+
-+/*
+ * af_can module init/exit functions
+ */
+
+ return -ENOMEM;
+
+ /*
-+ * Insert rx_alldev_list for reception on all devices.
++ * Insert can_rx_alldev_list for reception on all devices.
+ * This struct is zero initialized which is correct for the
+ * embedded hlist heads, the dev pointer, and the entries counter.
+ */
+
-+ spin_lock(&rcv_lists_lock);
-+ hlist_add_head_rcu(&rx_alldev_list.list, &rx_dev_list);
-+ spin_unlock(&rcv_lists_lock);
++ spin_lock(&can_rcvlists_lock);
++ hlist_add_head_rcu(&can_rx_alldev_list.list, &can_rx_dev_list);
++ spin_unlock(&can_rcvlists_lock);
+
+ if (stats_timer) {
+ /* the statistics are updated every second (timer triggered) */
-+ init_timer(&stattimer);
-+ stattimer.function = can_stat_update;
-+ stattimer.data = 0;
-+ /* update every second */
-+ stattimer.expires = round_jiffies(jiffies + HZ);
-+ /* start statistics timer */
-+ add_timer(&stattimer);
++ setup_timer(&can_stattimer, can_stat_update, 0);
++ mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
+ } else
-+ stattimer.function = NULL;
++ can_stattimer.function = NULL;
+
+ can_init_proc();
+
+ struct hlist_node *n, *next;
+
+ if (stats_timer)
-+ del_timer(&stattimer);
++ del_timer(&can_stattimer);
+
+ can_remove_proc();
+
+ unregister_netdevice_notifier(&can_netdev_notifier);
+ sock_unregister(PF_CAN);
+
-+ /* remove rx_dev_list */
-+ spin_lock(&rcv_lists_lock);
-+ hlist_del(&rx_alldev_list.list);
-+ hlist_for_each_entry_safe(d, n, next, &rx_dev_list, list) {
++ /* remove can_rx_dev_list */
++ spin_lock(&can_rcvlists_lock);
++ hlist_del(&can_rx_alldev_list.list);
++ hlist_for_each_entry_safe(d, n, next, &can_rx_dev_list, list) {
+ hlist_del(&d->list);
+ kfree(d);
+ }
-+ spin_unlock(&rcv_lists_lock);
++ spin_unlock(&can_rcvlists_lock);
+
+ kmem_cache_destroy(rcv_cache);
+}
Index: net-2.6.25/net/can/af_can.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/net/can/af_can.h 2007-11-14 13:04:49.000000000 +0100
-@@ -0,0 +1,120 @@
++++ net-2.6.25/net/can/af_can.h 2007-11-16 14:27:20.000000000 +0100
+@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
+ * All rights reserved.
+
+/* statistic structures */
+
++/* can be reset e.g. by can_init_stats() */
+struct s_stats {
+ unsigned long jiffies_init;
+
+ unsigned long rx_frames_delta;
+ unsigned long tx_frames_delta;
+ unsigned long matches_delta;
-+}; /* can be reset e.g. by can_init_stats() */
++};
+
++/* persistent statistics */
+struct s_pstats {
+ unsigned long stats_reset;
+ unsigned long user_reset;
+ unsigned long rcv_entries;
+ unsigned long rcv_entries_max;
-+}; /* persistent statistics */
++};
+
+/* function prototypes for the CAN networklayer procfs (proc.c) */
+extern void can_init_proc(void);
+extern void can_stat_update(unsigned long data);
+
+/* structures and variables from af_can.c needed in proc.c for reading */
-+extern struct timer_list stattimer; /* timer for statistics update */
-+extern struct s_stats stats; /* packet statistics */
-+extern struct s_pstats pstats; /* receive list statistics */
-+extern struct hlist_head rx_dev_list; /* rx dispatcher structures */
++extern struct timer_list can_stattimer; /* timer for statistics update */
++extern struct s_stats can_stats; /* packet statistics */
++extern struct s_pstats can_pstats; /* receive list statistics */
++extern struct hlist_head can_rx_dev_list; /* rx dispatcher structures */
+
+#endif /* AF_CAN_H */
Index: net-2.6.25/net/can/proc.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/net/can/proc.c 2007-11-14 13:04:49.000000000 +0100
-@@ -0,0 +1,532 @@
++++ net-2.6.25/net/can/proc.c 2007-11-16 14:27:37.000000000 +0100
+@@ -0,0 +1,533 @@
+/*
+ * proc.c - procfs support for Protocol family CAN core module
+ *
+{
+ /*
+ * This memset function is called from a timer context (when
-+ * stattimer is active which is the default) OR in a process
-+ * context (reading the proc_fs when stattimer is disabled).
++ * can_stattimer is active which is the default) OR in a process
++ * context (reading the proc_fs when can_stattimer is disabled).
+ */
-+ memset(&stats, 0, sizeof(stats));
-+ stats.jiffies_init = jiffies;
++ memset(&can_stats, 0, sizeof(can_stats));
++ can_stats.jiffies_init = jiffies;
+
-+ pstats.stats_reset++;
++ can_pstats.stats_reset++;
+
+ if (user_reset) {
+ user_reset = 0;
-+ pstats.user_reset++;
++ can_pstats.user_reset++;
+ }
+}
+
+ can_init_stats();
+
+ /* restart counting on jiffies overflow */
-+ if (j < stats.jiffies_init)
++ if (j < can_stats.jiffies_init)
+ can_init_stats();
+
+ /* prevent overflow in calc_rate() */
-+ if (stats.rx_frames > (ULONG_MAX / HZ))
++ if (can_stats.rx_frames > (ULONG_MAX / HZ))
+ can_init_stats();
+
+ /* prevent overflow in calc_rate() */
-+ if (stats.tx_frames > (ULONG_MAX / HZ))
++ if (can_stats.tx_frames > (ULONG_MAX / HZ))
+ can_init_stats();
+
+ /* matches overflow - very improbable */
-+ if (stats.matches > (ULONG_MAX / 100))
++ if (can_stats.matches > (ULONG_MAX / 100))
+ can_init_stats();
+
+ /* calc total values */
-+ if (stats.rx_frames)
-+ stats.total_rx_match_ratio = (stats.matches * 100) /
-+ stats.rx_frames;
++ if (can_stats.rx_frames)
++ can_stats.total_rx_match_ratio = (can_stats.matches * 100) /
++ can_stats.rx_frames;
+
-+ stats.total_tx_rate = calc_rate(stats.jiffies_init, j,
-+ stats.tx_frames);
-+ stats.total_rx_rate = calc_rate(stats.jiffies_init, j,
-+ stats.rx_frames);
++ can_stats.total_tx_rate = calc_rate(can_stats.jiffies_init, j,
++ can_stats.tx_frames);
++ can_stats.total_rx_rate = calc_rate(can_stats.jiffies_init, j,
++ can_stats.rx_frames);
+
+ /* calc current values */
-+ if (stats.rx_frames_delta)
-+ stats.current_rx_match_ratio =
-+ (stats.matches_delta * 100) / stats.rx_frames_delta;
++ if (can_stats.rx_frames_delta)
++ can_stats.current_rx_match_ratio =
++ (can_stats.matches_delta * 100) /
++ can_stats.rx_frames_delta;
+
-+ stats.current_tx_rate = calc_rate(0, HZ, stats.tx_frames_delta);
-+ stats.current_rx_rate = calc_rate(0, HZ, stats.rx_frames_delta);
++ can_stats.current_tx_rate = calc_rate(0, HZ, can_stats.tx_frames_delta);
++ can_stats.current_rx_rate = calc_rate(0, HZ, can_stats.rx_frames_delta);
+
+ /* check / update maximum values */
-+ if (stats.max_tx_rate < stats.current_tx_rate)
-+ stats.max_tx_rate = stats.current_tx_rate;
++ if (can_stats.max_tx_rate < can_stats.current_tx_rate)
++ can_stats.max_tx_rate = can_stats.current_tx_rate;
+
-+ if (stats.max_rx_rate < stats.current_rx_rate)
-+ stats.max_rx_rate = stats.current_rx_rate;
++ if (can_stats.max_rx_rate < can_stats.current_rx_rate)
++ can_stats.max_rx_rate = can_stats.current_rx_rate;
+
-+ if (stats.max_rx_match_ratio < stats.current_rx_match_ratio)
-+ stats.max_rx_match_ratio = stats.current_rx_match_ratio;
++ if (can_stats.max_rx_match_ratio < can_stats.current_rx_match_ratio)
++ can_stats.max_rx_match_ratio = can_stats.current_rx_match_ratio;
+
+ /* clear values for 'current rate' calculation */
-+ stats.tx_frames_delta = 0;
-+ stats.rx_frames_delta = 0;
-+ stats.matches_delta = 0;
++ can_stats.tx_frames_delta = 0;
++ can_stats.rx_frames_delta = 0;
++ can_stats.matches_delta = 0;
+
+ /* restart timer (one second) */
-+ stattimer.expires = round_jiffies(jiffies + HZ);
-+ add_timer(&stattimer);
++ mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
+}
+
+/*
+
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len,
-+ " %8ld transmitted frames (TXF)\n", stats.tx_frames);
++ " %8ld transmitted frames (TXF)\n",
++ can_stats.tx_frames);
+ len += snprintf(page + len, PAGE_SIZE - len,
-+ " %8ld received frames (RXF)\n", stats.rx_frames);
++ " %8ld received frames (RXF)\n", can_stats.rx_frames);
+ len += snprintf(page + len, PAGE_SIZE - len,
-+ " %8ld matched frames (RXMF)\n", stats.matches);
++ " %8ld matched frames (RXMF)\n", can_stats.matches);
+
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
+
-+ if (stattimer.function == can_stat_update) {
++ if (can_stattimer.function == can_stat_update) {
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld %% total match ratio (RXMR)\n",
-+ stats.total_rx_match_ratio);
++ can_stats.total_rx_match_ratio);
+
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s total tx rate (TXR)\n",
-+ stats.total_tx_rate);
++ can_stats.total_tx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s total rx rate (RXR)\n",
-+ stats.total_rx_rate);
++ can_stats.total_rx_rate);
+
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
+
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld %% current match ratio (CRXMR)\n",
-+ stats.current_rx_match_ratio);
++ can_stats.current_rx_match_ratio);
+
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s current tx rate (CTXR)\n",
-+ stats.current_tx_rate);
++ can_stats.current_tx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s current rx rate (CRXR)\n",
-+ stats.current_rx_rate);
++ can_stats.current_rx_rate);
+
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
+
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld %% max match ratio (MRXMR)\n",
-+ stats.max_rx_match_ratio);
++ can_stats.max_rx_match_ratio);
+
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s max tx rate (MTXR)\n",
-+ stats.max_tx_rate);
++ can_stats.max_tx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s max rx rate (MRXR)\n",
-+ stats.max_rx_rate);
++ can_stats.max_rx_rate);
+
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ }
+
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld current receive list entries (CRCV)\n",
-+ pstats.rcv_entries);
++ can_pstats.rcv_entries);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld maximum receive list entries (MRCV)\n",
-+ pstats.rcv_entries_max);
++ can_pstats.rcv_entries_max);
+
-+ if (pstats.stats_reset)
++ if (can_pstats.stats_reset)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "\n %8ld statistic resets (STR)\n",
-+ pstats.stats_reset);
++ can_pstats.stats_reset);
+
-+ if (pstats.user_reset)
++ if (can_pstats.user_reset)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld user statistic resets (USTR)\n",
-+ pstats.user_reset);
++ can_pstats.user_reset);
+
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
+
+
+ user_reset = 1;
+
-+ if (stattimer.function == can_stat_update) {
++ if (can_stattimer.function == can_stat_update) {
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "Scheduled statistic reset #%ld.\n",
-+ pstats.stats_reset + 1);
++ can_pstats.stats_reset + 1);
+
+ } else {
-+ if (stats.jiffies_init != jiffies)
++ if (can_stats.jiffies_init != jiffies)
+ can_init_stats();
+
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "Performed statistic reset #%ld.\n",
-+ pstats.stats_reset);
++ can_pstats.stats_reset);
+ }
+
+ *eof = 1;
+ "\nreceive list '%s':\n", rx_list_name[idx]);
+
+ rcu_read_lock();
-+ hlist_for_each_entry_rcu(d, n, &rx_dev_list, list) {
++ hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
+
+ if (!hlist_empty(&d->rx[idx])) {
+ len = can_print_recv_banner(page, len);
+ "\nreceive list 'rx_sff':\n");
+
+ rcu_read_lock();
-+ hlist_for_each_entry_rcu(d, n, &rx_dev_list, list) {
++ hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
+ int i, all_empty = 1;
+ /* check wether at least one list is non-empty */
+ for (i = 0; i < 0x800; i++)
Index: net-2.6.25/include/linux/can/error.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/include/linux/can/error.h 2007-11-14 13:04:49.000000000 +0100
++++ net-2.6.25/include/linux/can/error.h 2007-11-16 11:11:51.000000000 +0100
@@ -0,0 +1,93 @@
+/*
+ * linux/can/error.h
include/linux/can/raw.h | 31 +
net/can/Kconfig | 11
net/can/Makefile | 3
- net/can/raw.c | 811 ++++++++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 856 insertions(+)
+ net/can/raw.c | 763 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 808 insertions(+)
Index: net-2.6.25/include/linux/can/raw.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/include/linux/can/raw.h 2007-11-14 13:04:51.000000000 +0100
++++ net-2.6.25/include/linux/can/raw.h 2007-11-16 14:40:14.000000000 +0100
@@ -0,0 +1,31 @@
+/*
+ * linux/can/raw.h
+#endif
Index: net-2.6.25/net/can/Kconfig
===================================================================
---- net-2.6.25.orig/net/can/Kconfig 2007-11-14 13:04:49.000000000 +0100
-+++ net-2.6.25/net/can/Kconfig 2007-11-14 13:04:51.000000000 +0100
-@@ -16,6 +16,17 @@
+--- net-2.6.25.orig/net/can/Kconfig 2007-11-16 14:34:20.000000000 +0100
++++ net-2.6.25/net/can/Kconfig 2007-11-16 14:42:30.000000000 +0100
+@@ -15,3 +15,14 @@
+
If you want CAN support you should say Y here and also to the
specific driver for your controller(s) below.
-
++
+config CAN_RAW
+ tristate "Raw CAN Protocol (raw access with CAN-ID filtering)"
+ depends on CAN
+ most cases where no higher level protocol is being used. The raw
+ socket has several filter options e.g. ID masking / error frames.
+ To receive/send raw CAN messages, use AF_CAN with protocol CAN_RAW.
-+
- config CAN_DEBUG_CORE
- bool "CAN Core debugging messages"
- depends on CAN
Index: net-2.6.25/net/can/Makefile
===================================================================
---- net-2.6.25.orig/net/can/Makefile 2007-11-14 13:04:49.000000000 +0100
-+++ net-2.6.25/net/can/Makefile 2007-11-14 13:04:51.000000000 +0100
+--- net-2.6.25.orig/net/can/Makefile 2007-11-16 14:25:56.000000000 +0100
++++ net-2.6.25/net/can/Makefile 2007-11-16 14:40:14.000000000 +0100
@@ -4,3 +4,6 @@
obj-$(CONFIG_CAN) += can.o
Index: net-2.6.25/net/can/raw.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/net/can/raw.c 2007-11-14 13:04:51.000000000 +0100
-@@ -0,0 +1,811 @@
++++ net-2.6.25/net/can/raw.c 2007-11-16 14:43:29.000000000 +0100
+@@ -0,0 +1,763 @@
+/*
+ * raw.c - Raw sockets for protocol family CAN
+ *
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
+
-+#ifdef CONFIG_CAN_DEBUG_CORE
-+#define DBG_PREFIX "can-raw"
-+#define DBG_VAR raw_debug
-+static int raw_debug;
-+module_param_named(debug, raw_debug, int, S_IRUGO);
-+MODULE_PARM_DESC(debug, "debug print mask: 1:debug, 2:frames, 4:skbs");
-+#endif
-+
+#define MASK_ALL 0
+
+/*
+ struct sockaddr_can *addr;
+ int error;
+
-+ DBG("received skbuff %p, sk %p\n", skb, sk);
-+ DBG_SKB(skb);
-+
+ if (!ro->recv_own_msgs) {
+ /* check the received tx sock reference */
+ if (skb->sk == sk) {
-+ DBG("trashed own tx msg\n");
+ kfree_skb(skb);
+ return;
+ }
+ addr->can_ifindex = skb->dev->ifindex;
+
+ error = sock_queue_rcv_skb(sk, skb);
-+ if (error < 0) {
-+ DBG("sock_queue_rcv_skb failed: %d\n", error);
-+ DBG("freeing skbuff %p\n", skb);
++ if (error < 0)
+ kfree_skb(skb);
-+ }
+}
+
+static int raw_enable_filters(struct net_device *dev, struct sock *sk,
+ int i;
+
+ for (i = 0; i < count; i++) {
-+ DBG("filter can_id %08X, can_mask %08X%s, sk %p\n",
-+ filter[i].can_id, filter[i].can_mask,
-+ filter[i].can_id & CAN_INV_FILTER ? " (inv)" : "", sk);
-+
+ err = can_rx_register(dev, filter[i].can_id,
+ filter[i].can_mask,
+ raw_rcv, sk, "raw");
-+
+ if (err) {
+ /* clean up successfully registered filters */
+ while (--i >= 0)
+{
+ int i;
+
-+ for (i = 0; i < count; i++) {
-+ DBG("filter can_id %08X, can_mask %08X%s, sk %p\n",
-+ filter[i].can_id, filter[i].can_mask,
-+ filter[i].can_id & CAN_INV_FILTER ? " (inv)" : "", sk);
-+
++ for (i = 0; i < count; i++)
+ can_rx_unregister(dev, filter[i].can_id, filter[i].can_mask,
+ raw_rcv, sk);
-+ }
+}
+
+static inline void raw_disable_errfilter(struct net_device *dev,
+ struct raw_sock *ro = container_of(nb, struct raw_sock, notifier);
+ struct sock *sk = &ro->sk;
+
-+ DBG("msg %ld for dev %p (%s idx %d) sk %p ro->ifindex %d\n",
-+ msg, dev, dev->name, dev->ifindex, sk, ro->ifindex);
-+
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
+ struct sock *sk = sock->sk;
+ struct raw_sock *ro = raw_sk(sk);
+
-+ DBG("socket %p, sk %p, refcnt %d\n", sock, sk,
-+ atomic_read(&sk->sk_refcnt));
-+
+ unregister_netdevice_notifier(&ro->notifier);
+
+ lock_sock(sk);
+ int err = 0;
+ int notify_enetdown = 0;
+
-+ DBG("socket %p to device %d\n", sock, addr->can_ifindex);
-+
+ if (len < sizeof(*addr))
+ return -EINVAL;
+
+
+ dev = dev_get_by_index(&init_net, addr->can_ifindex);
+ if (!dev) {
-+ DBG("could not find device %d\n", addr->can_ifindex);
+ err = -ENODEV;
+ goto out;
+ }
+ if (dev->type != ARPHRD_CAN) {
-+ DBG("device %d no CAN device\n", addr->can_ifindex);
+ dev_put(dev);
+ err = -ENODEV;
+ goto out;
+ int ifindex;
+ int err;
+
-+ DBG("socket %p, sk %p\n", sock, sk);
-+
+ if (msg->msg_name) {
+ struct sockaddr_can *addr =
+ (struct sockaddr_can *)msg->msg_name;
+ ifindex = ro->ifindex;
+
+ dev = dev_get_by_index(&init_net, ifindex);
-+ if (!dev) {
-+ DBG("device %d not found\n", ifindex);
++ if (!dev)
+ return -ENXIO;
-+ }
+
+ skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT,
+ &err);
+ skb->dev = dev;
+ skb->sk = sk;
+
-+ DBG("sending skbuff to interface %d\n", ifindex);
-+ DBG_SKB(skb);
-+
+ err = can_send(skb, ro->loopback);
+
+ dev_put(dev);
+ int error = 0;
+ int noblock;
+
-+ DBG("socket %p, sk %p\n", sock, sk);
-+
+ noblock = flags & MSG_DONTWAIT;
+ flags &= ~MSG_DONTWAIT;
+
+ if (!skb)
+ return error;
+
-+ DBG("delivering skbuff %p\n", skb);
-+ DBG_SKB(skb);
-+
+ if (size < skb->len)
+ msg->msg_flags |= MSG_TRUNC;
+ else
+ memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
+ }
+
-+ DBG("freeing sock %p, skbuff %p\n", sk, skb);
+ skb_free_datagram(sk, skb);
+
+ return size;
include/linux/can/bcm.h | 65 +
net/can/Kconfig | 13
net/can/Makefile | 3
- net/can/bcm.c | 1763 ++++++++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 1844 insertions(+)
+ net/can/bcm.c | 1561 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 1642 insertions(+)
Index: net-2.6.25/include/linux/can/bcm.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/include/linux/can/bcm.h 2007-11-14 13:04:52.000000000 +0100
++++ net-2.6.25/include/linux/can/bcm.h 2007-11-16 14:44:48.000000000 +0100
@@ -0,0 +1,65 @@
+/*
+ * linux/can/bcm.h
+#endif /* CAN_BCM_H */
Index: net-2.6.25/net/can/Kconfig
===================================================================
---- net-2.6.25.orig/net/can/Kconfig 2007-11-14 13:04:51.000000000 +0100
-+++ net-2.6.25/net/can/Kconfig 2007-11-14 13:04:52.000000000 +0100
-@@ -27,6 +27,19 @@
+--- net-2.6.25.orig/net/can/Kconfig 2007-11-16 14:42:30.000000000 +0100
++++ net-2.6.25/net/can/Kconfig 2007-11-16 14:46:32.000000000 +0100
+@@ -26,3 +26,16 @@
+ most cases where no higher level protocol is being used. The raw
socket has several filter options e.g. ID masking / error frames.
To receive/send raw CAN messages, use AF_CAN with protocol CAN_RAW.
-
++
+config CAN_BCM
+ tristate "Broadcast Manager CAN Protocol (with content filtering)"
+ depends on CAN
+ You probably want to use the bcm socket in most cases where cyclic
+ CAN messages are used on the bus (e.g. in automotive environments).
+ To use the Broadcast Manager, use AF_CAN with protocol CAN_BCM.
-+
- config CAN_DEBUG_CORE
- bool "CAN Core debugging messages"
- depends on CAN
Index: net-2.6.25/net/can/Makefile
===================================================================
---- net-2.6.25.orig/net/can/Makefile 2007-11-14 13:04:51.000000000 +0100
-+++ net-2.6.25/net/can/Makefile 2007-11-14 13:04:52.000000000 +0100
+--- net-2.6.25.orig/net/can/Makefile 2007-11-16 14:40:14.000000000 +0100
++++ net-2.6.25/net/can/Makefile 2007-11-16 14:44:48.000000000 +0100
@@ -7,3 +7,6 @@
obj-$(CONFIG_CAN_RAW) += can-raw.o
Index: net-2.6.25/net/can/bcm.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/net/can/bcm.c 2007-11-14 13:04:52.000000000 +0100
-@@ -0,0 +1,1763 @@
++++ net-2.6.25/net/can/bcm.c 2007-11-16 14:47:57.000000000 +0100
+@@ -0,0 +1,1561 @@
+/*
+ * bcm.c - Broadcast Manager to filter/send (cyclic) CAN content
+ *
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
+
-+#ifdef CONFIG_CAN_DEBUG_CORE
-+#define DBG_PREFIX "can-bcm"
-+#define DBG_VAR bcm_debug
-+static int bcm_debug;
-+module_param_named(debug, bcm_debug, int, S_IRUGO);
-+MODULE_PARM_DESC(debug, "debug print mask: 1:debug, 2:frames, 4:skbs");
-+#endif
-+
+/* easy access to can_frame payload */
+static inline u64 GET_U64(const struct can_frame *cp)
+{
+ if (!ifindex)
+ return "any";
+
-+ dev = __dev_get_by_index(&init_net, ifindex); /* no usage counting */
++ /* no usage counting */
++ dev = __dev_get_by_index(&init_net, ifindex);
+ if (dev)
+ return dev->name;
+
+ struct net_device *dev;
+ struct can_frame *cf = &op->frames[op->currframe];
+
-+ DBG_FRAME("BCM: bcm_can_tx: sending frame", cf);
-+
+ /* no target device? => exit */
+ if (!op->ifindex)
+ return;
+ if (err < 0) {
+ struct bcm_sock *bo = bcm_sk(sk);
+
-+ DBG("sock_queue_rcv_skb failed: %d\n", err);
+ kfree_skb(skb);
+ /* don't care about overflows in this statistic */
+ bo->dropped_usr_msgs++;
+{
+ struct bcm_op *op = (struct bcm_op *)data;
+
-+ DBG("Called with bcm_op %p\n", op);
-+
+ if (op->j_ival1 && (op->count > 0)) {
+
+ op->count--;
+ struct bcm_msg_head msg_head;
+
+ /* create notification to user */
-+ DBG("sending TX_EXPIRED for can_id %03X\n",
-+ op->can_id);
-+
+ msg_head.opcode = TX_EXPIRED;
+ msg_head.flags = op->flags;
+ msg_head.count = op->count;
+ }
+ }
+
-+ DBG("count=%d j_ival1=%ld j_ival2=%ld\n",
-+ op->count, op->j_ival1, op->j_ival2);
-+
+ if (op->j_ival1 && (op->count > 0)) {
+
-+ op->timer.expires = jiffies + op->j_ival1;
-+ add_timer(&op->timer);
-+
-+ DBG("adding timer ival1. func=%p data=%p exp=0x%08X\n",
-+ op->timer.function,
-+ (char *) op->timer.data,
-+ (unsigned int) op->timer.expires);
-+
+ /* send (next) frame */
+ bcm_can_tx(op);
++ mod_timer(&op->timer, jiffies + op->j_ival1);
+
+ } else {
+ if (op->j_ival2) {
-+ op->timer.expires = jiffies + op->j_ival2;
-+ add_timer(&op->timer);
-+
-+ DBG("adding timer ival2. func=%p data=%p exp=0x%08X\n",
-+ op->timer.function,
-+ (char *) op->timer.data,
-+ (unsigned int) op->timer.expires);
+
+ /* send (next) frame */
+ bcm_can_tx(op);
-+
-+ } else
-+ DBG("no timer restart\n");
++ mod_timer(&op->timer, jiffies + op->j_ival2);
++ }
+ }
+
+ return;
+ if (op->frames_filtered > ULONG_MAX/100)
+ op->frames_filtered = op->frames_abs = 0;
+
-+ DBG("setting j_lastmsg to 0x%08X for rx_op %p\n",
-+ (unsigned int) op->j_lastmsg, op);
-+ DBG("sending notification\n");
-+
+ head.opcode = RX_CHANGED;
+ head.flags = op->flags;
+ head.count = op->count;
+
+ if (!(op->thrtimer.expires)) {
+ /* start the timer only the first time */
-+ op->thrtimer.expires = nexttx;
-+ add_timer(&op->thrtimer);
-+
-+ DBG("adding thrtimer. func=%p data=%p exp=0x%08X\n",
-+ op->thrtimer.function,
-+ (char *) op->thrtimer.data,
-+ (unsigned int) op->thrtimer.expires);
++ mod_timer(&op->thrtimer, nexttx);
+ }
+
+ } else {
+
+ if (!(op->last_frames[index].can_dlc & RX_RECV)) {
+ /* received data for the first time => send update to user */
-+ DBG("first time :)\n");
+ bcm_rx_update_and_send(op, &op->last_frames[index], rxdata);
+ return;
+ }
+
+ /* do a real check in can_frame data section */
+
-+ DBG("op->frames[index].data = 0x%016llx\n",
-+ GET_U64(&op->frames[index]));
-+ DBG("op->last_frames[index].data = 0x%016llx\n",
-+ GET_U64(&op->last_frames[index]));
-+ DBG("rxdata->data = 0x%016llx\n", GET_U64(rxdata));
-+
+ if ((GET_U64(&op->frames[index]) & GET_U64(rxdata)) !=
+ (GET_U64(&op->frames[index]) & GET_U64(&op->last_frames[index]))) {
-+ DBG("relevant data change :)\n");
+ bcm_rx_update_and_send(op, &op->last_frames[index], rxdata);
+ return;
+ }
+ /* do a real check in can_frame dlc */
+ if (rxdata->can_dlc != (op->last_frames[index].can_dlc &
+ BCM_CAN_DLC_MASK)) {
-+ DBG("dlc change :)\n");
+ bcm_rx_update_and_send(op, &op->last_frames[index],
+ rxdata);
+ return;
+ }
+ }
-+ DBG("no relevant change :(\n");
+}
+
+/*
+ if (op->flags & RX_NO_AUTOTIMER)
+ return;
+
-+ if (op->j_ival1) {
-+ op->timer.expires = jiffies + op->j_ival1;
-+
-+ DBG("adding rx timeout timer ival1. func=%p data=%p "
-+ "exp=0x%08X\n",
-+ op->timer.function,
-+ (char *) op->timer.data,
-+ (unsigned int) op->timer.expires);
-+
-+ add_timer(&op->timer);
-+ }
++ if (op->j_ival1)
++ mod_timer(&op->timer, jiffies + op->j_ival1);
+}
+
+/*
+ struct bcm_op *op = (struct bcm_op *)data;
+ struct bcm_msg_head msg_head;
+
-+ DBG("sending RX_TIMEOUT for can_id %03X. op is %p\n", op->can_id, op);
-+
+ msg_head.opcode = RX_TIMEOUT;
+ msg_head.flags = op->flags;
+ msg_head.count = op->count;
+ if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
+ /* clear received can_frames to indicate 'nothing received' */
+ memset(op->last_frames, 0, op->nframes * CFSIZ);
-+ DBG("RX_ANNOUNCE_RESTART\n");
+ }
+}
+
+ op->thrtimer.expires = 0;
+
+ if (op->nframes > 1) {
-+ DBG("sending MUX RX_CHANGED for can_id %03X. op is %p\n",
-+ op->can_id, op);
+ /* for MUX filter we start at index 1 */
+ for (i = 1; i < op->nframes; i++) {
+ if ((op->last_frames) &&
+ }
+
+ } else {
-+ DBG("sending simple RX_CHANGED for can_id %03X. op is %p\n",
-+ op->can_id, op);
+ /* for RX_FILTER_ID and simple filter */
+ if (op->last_frames && (op->last_frames[0].can_dlc & RX_THR)) {
+ op->last_frames[0].can_dlc &= ~RX_THR;
+ /* disable timeout */
+ del_timer(&op->timer);
+
-+ DBG("Called with bcm_op %p\n", op);
-+
+ if (skb->len == sizeof(rxframe)) {
+ memcpy(&rxframe, skb->data, sizeof(rxframe));
+ /* save rx timestamp */
+ /* update statistics */
+ op->frames_abs++;
+ kfree_skb(skb);
-+ DBG("got can_frame with can_id %03X\n", rxframe.can_id);
+
+ } else {
-+ DBG("Wrong skb->len = %d\n", skb->len);
+ kfree_skb(skb);
+ return;
+ }
+
-+ DBG_FRAME("BCM: bcm_rx_handler: CAN frame", &rxframe);
-+
-+ if (op->can_id != rxframe.can_id) {
-+ DBG("ERROR! Got wrong can_id %03X! Expected %03X.\n",
-+ rxframe.can_id, op->can_id);
++ if (op->can_id != rxframe.can_id)
+ return;
-+ }
+
+ if (op->flags & RX_RTR_FRAME) {
-+ /* send reply for RTR-request */
-+ DBG("RTR-request\n");
-+
-+ /* send op->frames[0] to CAN device */
++ /* send reply for RTR-request (placed in op->frames[0]) */
+ bcm_can_tx(op);
+ return;
+ }
+
+ if (op->flags & RX_FILTER_ID) {
+ /* the easiest case */
-+ DBG("Easy does it with RX_FILTER_ID\n");
-+
+ bcm_rx_update_and_send(op, &op->last_frames[0], &rxframe);
+ bcm_rx_starttimer(op);
+ return;
+
+ if (op->nframes == 1) {
+ /* simple compare with index 0 */
-+ DBG("Simple compare\n");
-+
+ bcm_rx_cmp_to_index(op, 0, &rxframe);
+ bcm_rx_starttimer(op);
+ return;
+ }
+
+ if (op->nframes > 1) {
-+ /* multiplex compare */
-+ DBG("Multiplex compare\n");
-+
+ /*
++ * multiplex compare
++ *
+ * find the first multiplex mask that fits.
+ * Remark: The MUX-mask is stored in index 0
+ */
+ if ((GET_U64(&op->frames[0]) & GET_U64(&rxframe)) ==
+ (GET_U64(&op->frames[0]) &
+ GET_U64(&op->frames[i]))) {
-+ DBG("found MUX index %d\n", i);
+ bcm_rx_cmp_to_index(op, i, &rxframe);
+ break;
+ }
+
+ list_for_each_entry_safe(op, n, ops, list) {
+ if ((op->can_id == can_id) && (op->ifindex == ifindex)) {
-+ DBG("removing rx_op %p for can_id %03X\n",
-+ op, op->can_id);
+
+ /*
+ * Don't care if we're bound or not (due to netdev
+
+ list_for_each_entry_safe(op, n, ops, list) {
+ if ((op->can_id == can_id) && (op->ifindex == ifindex)) {
-+ DBG("removing rx_op %p for can_id %03X\n",
-+ op, op->can_id);
+ list_del(&op->list);
+ bcm_remove_op(op);
+ return 1; /* done */
+{
+ struct bcm_op *op = bcm_find_op(ops, msg_head->can_id, ifindex);
+
-+ if (!op) {
-+ DBG("TRX_READ: did not find op for can_id %03X\n",
-+ msg_head->can_id);
++ if (!op)
+ return -EINVAL;
-+ }
+
-+ DBG("TRX_READ: sending status for can_id %03X\n",
-+ msg_head->can_id);
+ /* put current values into msg_head */
+ msg_head->flags = op->flags;
+ msg_head->count = op->count;
+ if (op) {
+ /* update existing BCM operation */
+
-+ DBG("TX_SETUP: modifying existing tx_op %p for can_id %03X\n",
-+ op, msg_head->can_id);
-+
+ /*
+ * Do we need more space for the can_frames than currently
+ * allocated? -> This is a _really_ unusual use-case and
+ if (!op)
+ return -ENOMEM;
+
-+ DBG("TX_SETUP: creating new tx_op %p for can_id %03X\n",
-+ op, msg_head->can_id);
-+
+ op->can_id = msg_head->can_id;
+
+ /* create array for can_frames and copy the data */
+
+ /* bcm_can_tx / bcm_tx_timeout_handler needs this */
+ op->sk = sk;
-+
+ op->ifindex = ifindex;
+
-+ /* initialize uninitialized (kmalloc) structure */
-+ init_timer(&op->timer);
++ /* initialize uninitialized (kzalloc) structure */
++ setup_timer(&op->timer, bcm_tx_timeout_handler,
++ (unsigned long)op);
+
+ /* currently unused in tx_ops */
+ init_timer(&op->thrtimer);
+
-+ /* handler for tx_ops */
-+ op->timer.function = bcm_tx_timeout_handler;
-+
-+ /* timer.data points to this op-structure */
-+ op->timer.data = (unsigned long)op;
-+
+ /* add this bcm_op to the list of the tx_ops */
+ list_add(&op->list, &bo->tx_ops);
+
+
+ if (op->flags & SETTIMER) {
+ /* set timer values */
-+
+ op->count = msg_head->count;
+ op->ival1 = msg_head->ival1;
+ op->ival2 = msg_head->ival2;
+ op->j_ival1 = rounded_tv2jif(&msg_head->ival1);
+ op->j_ival2 = rounded_tv2jif(&msg_head->ival2);
+
-+ DBG("TX_SETUP: SETTIMER count=%d j_ival1=%ld j_ival2=%ld\n",
-+ op->count, op->j_ival1, op->j_ival2);
-+
+ /* disable an active timer due to zero values? */
-+ if (!op->j_ival1 && !op->j_ival2) {
++ if (!op->j_ival1 && !op->j_ival2)
+ del_timer(&op->timer);
-+ DBG("TX_SETUP: SETTIMER disabled timer.\n");
-+ }
+ }
+
+ if ((op->flags & STARTTIMER) &&
+ ((op->j_ival1 && op->count) || op->j_ival2)) {
+
-+ del_timer(&op->timer);
-+
+ /* spec: send can_frame when starting timer */
+ op->flags |= TX_ANNOUNCE;
+
+ if (op->j_ival1 && (op->count > 0)) {
-+ op->timer.expires = jiffies + op->j_ival1;
+ /* op->count-- is done in bcm_tx_timeout_handler */
-+ DBG("TX_SETUP: adding timer ival1. func=%p data=%p "
-+ "exp=0x%08X\n",
-+ op->timer.function,
-+ (char *) op->timer.data,
-+ (unsigned int) op->timer.expires);
-+
-+ } else {
-+ op->timer.expires = jiffies + op->j_ival2;
-+ DBG("TX_SETUP: adding timer ival2. func=%p data=%p "
-+ "exp=0x%08X\n",
-+ op->timer.function,
-+ (char *) op->timer.data,
-+ (unsigned int) op->timer.expires);
-+ }
-+
-+ add_timer(&op->timer);
++ mod_timer(&op->timer, jiffies + op->j_ival1);
++ } else
++ mod_timer(&op->timer, jiffies + op->j_ival2);
+ }
+
+ if (op->flags & TX_ANNOUNCE)
+ if ((msg_head->flags & RX_FILTER_ID) || (!(msg_head->nframes))) {
+ /* be robust against wrong usage ... */
+ msg_head->flags |= RX_FILTER_ID;
-+ msg_head->nframes = 0; /* ignore trailing garbage */
++ /* ignore trailing garbage */
++ msg_head->nframes = 0;
+ }
+
+ if ((msg_head->flags & RX_RTR_FRAME) &&
+ ((msg_head->nframes != 1) ||
-+ (!(msg_head->can_id & CAN_RTR_FLAG)))) {
-+
-+ DBG("RX_SETUP: bad RX_RTR_FRAME setup!\n");
++ (!(msg_head->can_id & CAN_RTR_FLAG))))
+ return -EINVAL;
-+ }
+
+ /* check the given can_id */
+ op = bcm_find_op(&bo->rx_ops, msg_head->can_id, ifindex);
+ if (op) {
+ /* update existing BCM operation */
+
-+ DBG("RX_SETUP: modifying existing rx_op %p for can_id %03X\n",
-+ op, msg_head->can_id);
-+
+ /*
+ * Do we need more space for the can_frames than currently
+ * allocated? -> This is a _really_ unusual use-case and
+
+ } else {
+ /* insert new BCM operation for the given can_id */
-+
+ op = kzalloc(OPSIZ, GFP_KERNEL);
+ if (!op)
+ return -ENOMEM;
+
-+ DBG("RX_SETUP: creating new rx_op %p for can_id %03X\n",
-+ op, msg_head->can_id);
-+
+ op->can_id = msg_head->can_id;
+ op->nframes = msg_head->nframes;
+
+ }
+ }
+
++ /* bcm_can_tx / bcm_tx_timeout_handler needs this */
+ op->sk = sk;
+ op->ifindex = ifindex;
+
+ /* initialize uninitialized (kzalloc) structure */
-+ init_timer(&op->timer);
++ setup_timer(&op->timer, bcm_rx_timeout_handler,
++ (unsigned long)op);
+
+ /* init throttle timer for RX_CHANGED */
-+ init_timer(&op->thrtimer);
-+
-+ /* handler for rx timeouts */
-+ op->timer.function = bcm_rx_timeout_handler;
-+
-+ /* timer.data points to this op-structure */
-+ op->timer.data = (unsigned long)op;
-+
-+ /* handler for RX_CHANGED throttle timeouts */
-+ op->thrtimer.function = bcm_rx_thr_handler;
-+
-+ /* timer.data points to this op-structure */
-+ op->thrtimer.data = (unsigned long)op;
++ setup_timer(&op->thrtimer, bcm_rx_thr_handler,
++ (unsigned long)op);
+
+ /* mark disabled timer */
+ op->thrtimer.expires = 0;
+ op->j_ival1 = rounded_tv2jif(&msg_head->ival1);
+ op->j_ival2 = rounded_tv2jif(&msg_head->ival2);
+
-+ DBG("RX_SETUP: SETTIMER j_ival1=%ld j_ival2=%ld\n",
-+ op->j_ival1, op->j_ival2);
-+
+ /* disable an active timer due to zero value? */
-+ if (!op->j_ival1) {
++ if (!op->j_ival1)
+ del_timer(&op->timer);
-+ DBG("RX_SETUP: disabled timer rx timeouts.\n");
-+ }
+
+ /* free currently blocked msgs ? */
+ if (op->thrtimer.expires) {
-+ DBG("RX_SETUP: unblocking throttled msgs.\n");
-+ del_timer(&op->thrtimer);
+ /* send blocked msgs hereafter */
-+ op->thrtimer.expires = jiffies + 2;
-+ add_timer(&op->thrtimer);
++ mod_timer(&op->thrtimer, jiffies + 2);
+ }
++
+ /*
+ * if (op->j_ival2) is zero, no (new) throttling
+ * will happen. For details see functions
+ */
+ }
+
-+ if ((op->flags & STARTTIMER) && op->j_ival1) {
-+
-+ del_timer(&op->timer);
-+ op->timer.expires = jiffies + op->j_ival1;
-+
-+ DBG("RX_SETUP: adding timer ival1. func=%p data=%p"
-+ " exp=0x%08X\n",
-+ (char *) op->timer.function,
-+ (char *) op->timer.data,
-+ (unsigned int) op->timer.expires);
-+
-+ add_timer(&op->timer);
-+ }
++ if ((op->flags & STARTTIMER) && op->j_ival1)
++ mod_timer(&op->timer, jiffies + op->j_ival1);
+ }
+
+ /* now we can register for can_ids, if we added a new bcm_op */
+ if (do_rx_register) {
-+ DBG("RX_SETUP: can_rx_register() for can_id %03X. "
-+ "rx_op is %p\n", op->can_id, op);
-+
+ if (ifindex) {
+ struct net_device *dev;
+
+ struct net_device *dev;
+ int err;
+
-+ /* just copy and send one can_frame */
-+
-+ if (!ifindex) /* we need a real device to send frames */
++ /* we need a real device to send frames */
++ if (!ifindex)
+ return -ENODEV;
+
+ skb = alloc_skb(CFSIZ, GFP_KERNEL);
+ return err;
+ }
+
-+ DBG_FRAME("BCM: TX_SEND: sending frame",
-+ (struct can_frame *)skb->data);
-+
+ dev = dev_get_by_index(&init_net, ifindex);
+ if (!dev) {
+ kfree_skb(skb);
+ struct bcm_msg_head msg_head;
+ int ret; /* read bytes or error codes as return value */
+
-+ if (!bo->bound) {
-+ DBG("sock %p not bound\n", sk);
++ if (!bo->bound)
+ return -ENOTCONN;
-+ }
+
+ /* check for alternative ifindex for this bcm_op */
+
+ if (addr->can_family != AF_CAN)
+ return -EINVAL;
+
-+ ifindex = addr->can_ifindex; /* ifindex from sendto() */
++ /* ifindex from sendto() */
++ ifindex = addr->can_ifindex;
+
+ if (ifindex) {
+ struct net_device *dev;
+
+ dev = dev_get_by_index(&init_net, ifindex);
-+ if (!dev) {
-+ DBG("device %d not found\n", ifindex);
++ if (!dev)
+ return -ENODEV;
-+ }
+
+ if (dev->type != ARPHRD_CAN) {
-+ DBG("device %d no CAN device\n", ifindex);
+ dev_put(dev);
+ return -ENODEV;
+ }
+ if (ret < 0)
+ return ret;
+
-+ DBG("opcode %d for can_id %03X\n", msg_head.opcode, msg_head.can_id);
-+
+ lock_sock(sk);
+
+ switch (msg_head.opcode) {
+ break;
+
+ default:
-+ DBG("Unknown opcode %d\n", msg_head.opcode);
+ ret = -EINVAL;
+ break;
+ }
+ struct bcm_op *op;
+ int notify_enodev = 0;
+
-+ DBG("msg %ld for dev %p (%s idx %d) sk %p bo->ifindex %d\n",
-+ msg, dev, dev->name, dev->ifindex, sk, bo->ifindex);
-+
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
+ struct bcm_sock *bo = bcm_sk(sk);
+ struct bcm_op *op, *next;
+
-+ DBG("socket %p, sk %p\n", sock, sk);
-+
+ /* remove bcm_ops, timer, rx_unregister(), etc. */
+
+ unregister_netdevice_notifier(&bo->notifier);
+
+ lock_sock(sk);
+
-+ list_for_each_entry_safe(op, next, &bo->tx_ops, list) {
-+ DBG("removing tx_op %p for can_id %03X\n", op, op->can_id);
++ list_for_each_entry_safe(op, next, &bo->tx_ops, list)
+ bcm_remove_op(op);
-+ }
+
+ list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
-+ DBG("removing rx_op %p for can_id %03X\n", op, op->can_id);
-+
+ /*
+ * Don't care if we're bound or not (due to netdev problems)
+ * can_rx_unregister() is always a save thing to do here.
+ struct net_device *dev;
+
+ dev = dev_get_by_index(&init_net, addr->can_ifindex);
-+ if (!dev) {
-+ DBG("could not find device index %d\n",
-+ addr->can_ifindex);
++ if (!dev)
+ return -ENODEV;
-+ }
+
+ if (dev->type != ARPHRD_CAN) {
-+ DBG("device %d no CAN device\n", addr->can_ifindex);
+ dev_put(dev);
+ return -ENODEV;
+ }
+ bo->ifindex = dev->ifindex;
+ dev_put(dev);
+
-+ DBG("socket %p bound to device %s (idx %d)\n",
-+ sock, dev->name, dev->ifindex);
-+
+ } else {
+ /* no interface reference for ifindex = 0 ('any' CAN device) */
+ bo->ifindex = 0;
+ int noblock;
+ int err;
+
-+ DBG("socket %p, sk %p\n", sock, sk);
-+
+ noblock = flags & MSG_DONTWAIT;
+ flags &= ~MSG_DONTWAIT;
+ skb = skb_recv_datagram(sk, flags, noblock, &error);
+ if (!skb)
+ return error;
+
-+ DBG("delivering skbuff %p\n", skb);
-+ DBG_SKB(skb);
-+
+ if (skb->len < size)
+ size = skb->len;
+
+ memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
+ }
+
-+ DBG("freeing sock %p, skbuff %p\n", sk, skb);
+ skb_free_datagram(sk, skb);
+
+ return size;
---
drivers/net/Makefile | 1
- drivers/net/can/Kconfig | 25 +++++
+ drivers/net/can/Kconfig | 25 ++++++
drivers/net/can/Makefile | 5 +
- drivers/net/can/vcan.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/net/can/vcan.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++
net/can/Kconfig | 3
- 5 files changed, 241 insertions(+)
+ 5 files changed, 203 insertions(+)
Index: net-2.6.25/drivers/net/Makefile
===================================================================
---- net-2.6.25.orig/drivers/net/Makefile 2007-11-14 13:04:24.000000000 +0100
-+++ net-2.6.25/drivers/net/Makefile 2007-11-14 13:04:54.000000000 +0100
+--- net-2.6.25.orig/drivers/net/Makefile 2007-11-16 14:50:12.000000000 +0100
++++ net-2.6.25/drivers/net/Makefile 2007-11-16 14:50:18.000000000 +0100
@@ -12,6 +12,7 @@
obj-$(CONFIG_CHELSIO_T1) += chelsio/
obj-$(CONFIG_CHELSIO_T3) += cxgb3/
Index: net-2.6.25/drivers/net/can/Kconfig
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/drivers/net/can/Kconfig 2007-11-14 13:04:54.000000000 +0100
++++ net-2.6.25/drivers/net/can/Kconfig 2007-11-16 14:50:18.000000000 +0100
@@ -0,0 +1,25 @@
+menu "CAN Device Drivers"
+ depends on CAN
Index: net-2.6.25/drivers/net/can/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/drivers/net/can/Makefile 2007-11-14 13:04:54.000000000 +0100
++++ net-2.6.25/drivers/net/can/Makefile 2007-11-16 14:50:18.000000000 +0100
@@ -0,0 +1,5 @@
+#
+# Makefile for the Linux Controller Area Network drivers.
Index: net-2.6.25/drivers/net/can/vcan.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/drivers/net/can/vcan.c 2007-11-14 13:04:54.000000000 +0100
-@@ -0,0 +1,207 @@
++++ net-2.6.25/drivers/net/can/vcan.c 2007-11-16 14:51:53.000000000 +0100
+@@ -0,0 +1,169 @@
+/*
+ * vcan.c - Virtual CAN interface
+ *
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
+
-+#ifdef CONFIG_CAN_DEBUG_DEVICES
-+static int vcan_debug;
-+module_param_named(debug, vcan_debug, int, S_IRUGO);
-+#endif
-+
-+/* To be moved to linux/can/dev.h */
-+#ifdef CONFIG_CAN_DEBUG_DEVICES
-+#define DBG(fmt, args...) (vcan_debug & 1 ? \
-+ printk(KERN_DEBUG "vcan %s: " fmt, \
-+ __func__, ##args) : 0)
-+#else
-+#define DBG(fmt, args...)
-+#endif
-+
+
+/*
+ * CAN test feature:
+MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)");
+
+
-+static int vcan_open(struct net_device *dev)
-+{
-+ DBG("%s: interface up\n", dev->name);
-+
-+ netif_start_queue(dev);
-+ return 0;
-+}
-+
-+static int vcan_stop(struct net_device *dev)
-+{
-+ DBG("%s: interface down\n", dev->name);
-+
-+ netif_stop_queue(dev);
-+ return 0;
-+}
-+
+static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_device_stats *stats = &dev->stats;
+ skb->dev = dev;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
-+ DBG("received skbuff on interface %d\n", dev->ifindex);
-+
+ netif_rx(skb);
+}
+
+ struct net_device_stats *stats = &dev->stats;
+ int loop;
+
-+ DBG("sending skbuff on interface %s\n", dev->name);
-+
+ stats->tx_packets++;
+ stats->tx_bytes += skb->len;
+
+ stats->rx_bytes += skb->len;
+ }
+ kfree_skb(skb);
-+ return 0;
++ return NETDEV_TX_OK;
+ }
+
+ /* perform standard echo handling for CAN network interfaces */
+
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!skb)
-+ return 0;
++ return NETDEV_TX_OK;
+
+ /* receive with packet counting */
+ skb->sk = srcsk;
+ /* no looped packets => no counting */
+ kfree_skb(skb);
+ }
-+ return 0;
++ return NETDEV_TX_OK;
+}
+
+static void vcan_setup(struct net_device *dev)
+{
-+ DBG("dev %s\n", dev->name);
-+
+ dev->type = ARPHRD_CAN;
+ dev->mtu = sizeof(struct can_frame);
+ dev->hard_header_len = 0;
+ if (echo)
+ dev->flags |= IFF_ECHO;
+
-+ dev->open = vcan_open;
-+ dev->stop = vcan_stop;
+ dev->hard_start_xmit = vcan_tx;
+ dev->destructor = free_netdev;
+}
+module_exit(vcan_cleanup_module);
Index: net-2.6.25/net/can/Kconfig
===================================================================
---- net-2.6.25.orig/net/can/Kconfig 2007-11-14 13:04:52.000000000 +0100
-+++ net-2.6.25/net/can/Kconfig 2007-11-14 13:04:54.000000000 +0100
-@@ -47,3 +47,6 @@
- Say Y here if you want the CAN core to produce a bunch of debug
- messages. Select this if you are having a problem with CAN
- support and want to see more of what is going on.
+--- net-2.6.25.orig/net/can/Kconfig 2007-11-16 14:50:18.000000000 +0100
++++ net-2.6.25/net/can/Kconfig 2007-11-16 14:50:18.000000000 +0100
+@@ -39,3 +39,6 @@
+ You probably want to use the bcm socket in most cases where cyclic
+ CAN messages are used on the bus (e.g. in automotive environments).
+ To use the Broadcast Manager, use AF_CAN with protocol CAN_BCM.
+
+
+source "drivers/net/can/Kconfig"
---
Documentation/networking/00-INDEX | 2
- Documentation/networking/can.txt | 637 ++++++++++++++++++++++++++++++++++++++
- 2 files changed, 639 insertions(+)
+ Documentation/networking/can.txt | 629 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 631 insertions(+)
Index: net-2.6.25/Documentation/networking/can.txt
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ net-2.6.25/Documentation/networking/can.txt 2007-11-14 13:04:57.000000000 +0100
-@@ -0,0 +1,637 @@
++++ net-2.6.25/Documentation/networking/can.txt 2007-11-16 14:56:31.000000000 +0100
+@@ -0,0 +1,629 @@
+============================================================================
+
+can.txt
+ invoked at can.ko module start time by default. This timer can be
+ disabled by using stattimer=0 on the module comandline.
+
-+ - debug: When the Kconfig option CONFIG_CAN_DEBUG_CORE is set at
-+ compile time, the debug output code is compiled into the module.
-+ debug = 0x01 => print general debug information
-+ debug = 0x02 => print content of processed CAN frames
-+ debug = 0x04 => print content of processed socket buffers
-+
-+ It is possible to use ORed values e.g. 3 or 7 for an output of
-+ all available debug information. Using 0x02 and 0x04 may flood
-+ your kernel log - so be careful.
++ - debug: (removed since SocketCAN SVN r546)
+
+ 5.2 procfs content
+
+ Michael Schulze (driver layer loopback requirement, RT CAN drivers review)
Index: net-2.6.25/Documentation/networking/00-INDEX
===================================================================
---- net-2.6.25.orig/Documentation/networking/00-INDEX 2007-11-14 13:04:23.000000000 +0100
-+++ net-2.6.25/Documentation/networking/00-INDEX 2007-11-14 13:04:57.000000000 +0100
+--- net-2.6.25.orig/Documentation/networking/00-INDEX 2007-11-16 14:52:07.000000000 +0100
++++ net-2.6.25/Documentation/networking/00-INDEX 2007-11-16 14:55:44.000000000 +0100
@@ -24,6 +24,8 @@
- info on the driver for Baycom style amateur radio modems
bridge.txt
SUBJECT
-CAN: New PF_CAN protocol family for 2.6.25
+CAN: New PF_CAN protocol family for 2.6.25, update
ESUBJECT
Hello Dave, hello Patrick,
-this patch series that adds the PF_CAN protocol family for the
+this patch series adds the PF_CAN protocol family for the
Controller Area Network. Since our last post we have changed:
-* Fix a bug causing NULL pointer dereference when module autoloading fails.
-* Initialize skb using skb_reset_{transport,network}_header().
-* Use sock_alloc_send_skb() instead of alloc_skb().
-* Adapt to changes in sk_alloc() parameter list.
-* Rename some local variables for readability.
+* Remove vcan_open() and vcan_stop().
+* return NETDEV_TX_OK instead of 0.
+* Add can_ prefix to some global vars.
+* Remove all debug code completely.
+* Cleanup of timer code.
This patch series applies against net-2.6.25 and is derived from Subversion
-revision r542 of http://svn.berlios.de/svnroot/repos/socketcan.
+revision r560 of http://svn.berlios.de/svnroot/repos/socketcan.
It can be found in the directory
http://svn.berlios.de/svnroot/repos/socketcan/trunk/patch-series/<version>.
-Thanks very much for your work!
-
-Best regards,
-
Urs Thuermann
Oliver Hartkopp
+The changes in try #11 were:
+
+* Fix a bug causing NULL pointer dereference when module autoloading fails.
+* Initialize skb using skb_reset_{transport,network}_header().
+* Use sock_alloc_send_skb() instead of alloc_skb().
+* Adapt to changes in sk_alloc() parameter list.
+* Rename some local variables for readability.
The changes in try #10 were: