aboutsummaryrefslogtreecommitdiffstats
path: root/net/can
diff options
context:
space:
mode:
authorOliver Hartkopp <oliver.hartkopp@volkswagen.de>2007-11-16 18:52:17 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:54:10 -0500
commit0d66548a10cbbe0ef256852d63d30603f0f73f9b (patch)
tree58c91033f88014c6a25b4d105a721bc58ec35f2c /net/can
parentcd05acfe65ed2cf2db683fa9a6adb8d35635263b (diff)
[CAN]: Add PF_CAN core module
This patch adds the CAN core functionality but no protocols or drivers. No protocol implementations are included here. They come as separate patches. Protocol numbers are already in include/linux/can.h. Signed-off-by: Oliver Hartkopp <oliver.hartkopp@volkswagen.de> Signed-off-by: Urs Thuermann <urs.thuermann@volkswagen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/can')
-rw-r--r--net/can/Kconfig17
-rw-r--r--net/can/Makefile6
-rw-r--r--net/can/af_can.c861
-rw-r--r--net/can/af_can.h122
-rw-r--r--net/can/proc.c533
5 files changed, 1539 insertions, 0 deletions
diff --git a/net/can/Kconfig b/net/can/Kconfig
new file mode 100644
index 000000000000..8b92790747e5
--- /dev/null
+++ b/net/can/Kconfig
@@ -0,0 +1,17 @@
1#
2# Controller Area Network (CAN) network layer core configuration
3#
4
5menuconfig CAN
6 depends on NET
7 tristate "CAN bus subsystem support"
8 ---help---
9 Controller Area Network (CAN) is a slow (up to 1Mbit/s) serial
10 communications protocol which was developed by Bosch in
11 1991, mainly for automotive, but now widely used in marine
12 (NMEA2000), industrial, and medical applications.
13 More information on the CAN network protocol family PF_CAN
14 is contained in <Documentation/networking/can.txt>.
15
16 If you want CAN support you should say Y here and also to the
17 specific driver for your controller(s) below.
diff --git a/net/can/Makefile b/net/can/Makefile
new file mode 100644
index 000000000000..4c7563c2ccb2
--- /dev/null
+++ b/net/can/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the Linux Controller Area Network core.
3#
4
5obj-$(CONFIG_CAN) += can.o
6can-objs := af_can.o proc.o
diff --git a/net/can/af_can.c b/net/can/af_can.c
new file mode 100644
index 000000000000..5158e886630f
--- /dev/null
+++ b/net/can/af_can.c
@@ -0,0 +1,861 @@
1/*
2 * af_can.c - Protocol family CAN core module
3 * (used by different CAN protocol modules)
4 *
5 * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of Volkswagen nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * Alternatively, provided that this notice is retained in full, this
21 * software may be distributed under the terms of the GNU General
22 * Public License ("GPL") version 2, in which case the provisions of the
23 * GPL apply INSTEAD OF those given above.
24 *
25 * The provided data structures and external interfaces from this code
26 * are not restricted to be used by modules with a GPL compatible license.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39 * DAMAGE.
40 *
41 * Send feedback to <socketcan-users@lists.berlios.de>
42 *
43 */
44
45#include <linux/module.h>
46#include <linux/init.h>
47#include <linux/kmod.h>
48#include <linux/slab.h>
49#include <linux/list.h>
50#include <linux/spinlock.h>
51#include <linux/rcupdate.h>
52#include <linux/uaccess.h>
53#include <linux/net.h>
54#include <linux/netdevice.h>
55#include <linux/socket.h>
56#include <linux/if_ether.h>
57#include <linux/if_arp.h>
58#include <linux/skbuff.h>
59#include <linux/can.h>
60#include <linux/can/core.h>
61#include <net/net_namespace.h>
62#include <net/sock.h>
63
64#include "af_can.h"
65
66static __initdata const char banner[] = KERN_INFO
67 "can: controller area network core (" CAN_VERSION_STRING ")\n";
68
69MODULE_DESCRIPTION("Controller Area Network PF_CAN core");
70MODULE_LICENSE("Dual BSD/GPL");
71MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>, "
72 "Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
73
74MODULE_ALIAS_NETPROTO(PF_CAN);
75
76static int stats_timer __read_mostly = 1;
77module_param(stats_timer, int, S_IRUGO);
78MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)");
79
80HLIST_HEAD(can_rx_dev_list);
81static struct dev_rcv_lists can_rx_alldev_list;
82static DEFINE_SPINLOCK(can_rcvlists_lock);
83
84static struct kmem_cache *rcv_cache __read_mostly;
85
86/* table of registered CAN protocols */
87static struct can_proto *proto_tab[CAN_NPROTO] __read_mostly;
88static DEFINE_SPINLOCK(proto_tab_lock);
89
90struct timer_list can_stattimer; /* timer for statistics update */
91struct s_stats can_stats; /* packet statistics */
92struct s_pstats can_pstats; /* receive list statistics */
93
94/*
95 * af_can socket functions
96 */
97
98static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
99{
100 struct sock *sk = sock->sk;
101
102 switch (cmd) {
103
104 case SIOCGSTAMP:
105 return sock_get_timestamp(sk, (struct timeval __user *)arg);
106
107 default:
108 return -ENOIOCTLCMD;
109 }
110}
111
112static void can_sock_destruct(struct sock *sk)
113{
114 skb_queue_purge(&sk->sk_receive_queue);
115}
116
117static int can_create(struct net *net, struct socket *sock, int protocol)
118{
119 struct sock *sk;
120 struct can_proto *cp;
121 char module_name[sizeof("can-proto-000")];
122 int err = 0;
123
124 sock->state = SS_UNCONNECTED;
125
126 if (protocol < 0 || protocol >= CAN_NPROTO)
127 return -EINVAL;
128
129 if (net != &init_net)
130 return -EAFNOSUPPORT;
131
132 /* try to load protocol module, when CONFIG_KMOD is defined */
133 if (!proto_tab[protocol]) {
134 sprintf(module_name, "can-proto-%d", protocol);
135 err = request_module(module_name);
136
137 /*
138 * In case of error we only print a message but don't
139 * return the error code immediately. Below we will
140 * return -EPROTONOSUPPORT
141 */
142 if (err == -ENOSYS) {
143 if (printk_ratelimit())
144 printk(KERN_INFO "can: request_module(%s)"
145 " not implemented.\n", module_name);
146 } else if (err) {
147 if (printk_ratelimit())
148 printk(KERN_ERR "can: request_module(%s)"
149 " failed.\n", module_name);
150 }
151 }
152
153 spin_lock(&proto_tab_lock);
154 cp = proto_tab[protocol];
155 if (cp && !try_module_get(cp->prot->owner))
156 cp = NULL;
157 spin_unlock(&proto_tab_lock);
158
159 /* check for available protocol and correct usage */
160
161 if (!cp)
162 return -EPROTONOSUPPORT;
163
164 if (cp->type != sock->type) {
165 err = -EPROTONOSUPPORT;
166 goto errout;
167 }
168
169 if (cp->capability >= 0 && !capable(cp->capability)) {
170 err = -EPERM;
171 goto errout;
172 }
173
174 sock->ops = cp->ops;
175
176 sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot);
177 if (!sk) {
178 err = -ENOMEM;
179 goto errout;
180 }
181
182 sock_init_data(sock, sk);
183 sk->sk_destruct = can_sock_destruct;
184
185 if (sk->sk_prot->init)
186 err = sk->sk_prot->init(sk);
187
188 if (err) {
189 /* release sk on errors */
190 sock_orphan(sk);
191 sock_put(sk);
192 }
193
194 errout:
195 module_put(cp->prot->owner);
196 return err;
197}
198
199/*
200 * af_can tx path
201 */
202
203/**
204 * can_send - transmit a CAN frame (optional with local loopback)
205 * @skb: pointer to socket buffer with CAN frame in data section
206 * @loop: loopback for listeners on local CAN sockets (recommended default!)
207 *
208 * Return:
209 * 0 on success
210 * -ENETDOWN when the selected interface is down
211 * -ENOBUFS on full driver queue (see net_xmit_errno())
212 * -ENOMEM when local loopback failed at calling skb_clone()
213 * -EPERM when trying to send on a non-CAN interface
214 */
215int can_send(struct sk_buff *skb, int loop)
216{
217 int err;
218
219 if (skb->dev->type != ARPHRD_CAN) {
220 kfree_skb(skb);
221 return -EPERM;
222 }
223
224 if (!(skb->dev->flags & IFF_UP)) {
225 kfree_skb(skb);
226 return -ENETDOWN;
227 }
228
229 skb->protocol = htons(ETH_P_CAN);
230 skb_reset_network_header(skb);
231 skb_reset_transport_header(skb);
232
233 if (loop) {
234 /* local loopback of sent CAN frames */
235
236 /* indication for the CAN driver: do loopback */
237 skb->pkt_type = PACKET_LOOPBACK;
238
239 /*
240 * The reference to the originating sock may be required
241 * by the receiving socket to check whether the frame is
242 * its own. Example: can_raw sockopt CAN_RAW_RECV_OWN_MSGS
243 * Therefore we have to ensure that skb->sk remains the
244 * reference to the originating sock by restoring skb->sk
245 * after each skb_clone() or skb_orphan() usage.
246 */
247
248 if (!(skb->dev->flags & IFF_ECHO)) {
249 /*
250 * If the interface is not capable to do loopback
251 * itself, we do it here.
252 */
253 struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
254
255 if (!newskb) {
256 kfree_skb(skb);
257 return -ENOMEM;
258 }
259
260 newskb->sk = skb->sk;
261 newskb->ip_summed = CHECKSUM_UNNECESSARY;
262 newskb->pkt_type = PACKET_BROADCAST;
263 netif_rx(newskb);
264 }
265 } else {
266 /* indication for the CAN driver: no loopback required */
267 skb->pkt_type = PACKET_HOST;
268 }
269
270 /* send to netdevice */
271 err = dev_queue_xmit(skb);
272 if (err > 0)
273 err = net_xmit_errno(err);
274
275 /* update statistics */
276 can_stats.tx_frames++;
277 can_stats.tx_frames_delta++;
278
279 return err;
280}
281EXPORT_SYMBOL(can_send);
282
283/*
284 * af_can rx path
285 */
286
287static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
288{
289 struct dev_rcv_lists *d = NULL;
290 struct hlist_node *n;
291
292 /*
293 * find receive list for this device
294 *
295 * The hlist_for_each_entry*() macros curse through the list
296 * using the pointer variable n and set d to the containing
297 * struct in each list iteration. Therefore, after list
298 * iteration, d is unmodified when the list is empty, and it
299 * points to last list element, when the list is non-empty
300 * but no match in the loop body is found. I.e. d is *not*
301 * NULL when no match is found. We can, however, use the
302 * cursor variable n to decide if a match was found.
303 */
304
305 hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
306 if (d->dev == dev)
307 break;
308 }
309
310 return n ? d : NULL;
311}
312
313static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
314 struct dev_rcv_lists *d)
315{
316 canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */
317
318 /* filter error frames */
319 if (*mask & CAN_ERR_FLAG) {
320 /* clear CAN_ERR_FLAG in list entry */
321 *mask &= CAN_ERR_MASK;
322 return &d->rx[RX_ERR];
323 }
324
325 /* ensure valid values in can_mask */
326 if (*mask & CAN_EFF_FLAG)
327 *mask &= (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG);
328 else
329 *mask &= (CAN_SFF_MASK | CAN_RTR_FLAG);
330
331 /* reduce condition testing at receive time */
332 *can_id &= *mask;
333
334 /* inverse can_id/can_mask filter */
335 if (inv)
336 return &d->rx[RX_INV];
337
338 /* mask == 0 => no condition testing at receive time */
339 if (!(*mask))
340 return &d->rx[RX_ALL];
341
342 /* use extra filterset for the subscription of exactly *ONE* can_id */
343 if (*can_id & CAN_EFF_FLAG) {
344 if (*mask == (CAN_EFF_MASK | CAN_EFF_FLAG)) {
345 /* RFC: a use-case for hash-tables in the future? */
346 return &d->rx[RX_EFF];
347 }
348 } else {
349 if (*mask == CAN_SFF_MASK)
350 return &d->rx_sff[*can_id];
351 }
352
353 /* default: filter via can_id/can_mask */
354 return &d->rx[RX_FIL];
355}
356
357/**
358 * can_rx_register - subscribe CAN frames from a specific interface
359 * @dev: pointer to netdevice (NULL => subcribe from 'all' CAN devices list)
360 * @can_id: CAN identifier (see description)
361 * @mask: CAN mask (see description)
362 * @func: callback function on filter match
363 * @data: returned parameter for callback function
364 * @ident: string for calling module indentification
365 *
366 * Description:
367 * Invokes the callback function with the received sk_buff and the given
368 * parameter 'data' on a matching receive filter. A filter matches, when
369 *
370 * <received_can_id> & mask == can_id & mask
371 *
372 * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
373 * filter for error frames (CAN_ERR_FLAG bit set in mask).
374 *
375 * Return:
376 * 0 on success
377 * -ENOMEM on missing cache mem to create subscription entry
378 * -ENODEV unknown device
379 */
380int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
381 void (*func)(struct sk_buff *, void *), void *data,
382 char *ident)
383{
384 struct receiver *r;
385 struct hlist_head *rl;
386 struct dev_rcv_lists *d;
387 int err = 0;
388
389 /* insert new receiver (dev,canid,mask) -> (func,data) */
390
391 r = kmem_cache_alloc(rcv_cache, GFP_KERNEL);
392 if (!r)
393 return -ENOMEM;
394
395 spin_lock(&can_rcvlists_lock);
396
397 d = find_dev_rcv_lists(dev);
398 if (d) {
399 rl = find_rcv_list(&can_id, &mask, d);
400
401 r->can_id = can_id;
402 r->mask = mask;
403 r->matches = 0;
404 r->func = func;
405 r->data = data;
406 r->ident = ident;
407
408 hlist_add_head_rcu(&r->list, rl);
409 d->entries++;
410
411 can_pstats.rcv_entries++;
412 if (can_pstats.rcv_entries_max < can_pstats.rcv_entries)
413 can_pstats.rcv_entries_max = can_pstats.rcv_entries;
414 } else {
415 kmem_cache_free(rcv_cache, r);
416 err = -ENODEV;
417 }
418
419 spin_unlock(&can_rcvlists_lock);
420
421 return err;
422}
423EXPORT_SYMBOL(can_rx_register);
424
425/*
426 * can_rx_delete_device - rcu callback for dev_rcv_lists structure removal
427 */
428static void can_rx_delete_device(struct rcu_head *rp)
429{
430 struct dev_rcv_lists *d = container_of(rp, struct dev_rcv_lists, rcu);
431
432 kfree(d);
433}
434
435/*
436 * can_rx_delete_receiver - rcu callback for single receiver entry removal
437 */
438static void can_rx_delete_receiver(struct rcu_head *rp)
439{
440 struct receiver *r = container_of(rp, struct receiver, rcu);
441
442 kmem_cache_free(rcv_cache, r);
443}
444
445/**
446 * can_rx_unregister - unsubscribe CAN frames from a specific interface
447 * @dev: pointer to netdevice (NULL => unsubcribe from 'all' CAN devices list)
448 * @can_id: CAN identifier
449 * @mask: CAN mask
450 * @func: callback function on filter match
451 * @data: returned parameter for callback function
452 *
453 * Description:
454 * Removes subscription entry depending on given (subscription) values.
455 */
456void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
457 void (*func)(struct sk_buff *, void *), void *data)
458{
459 struct receiver *r = NULL;
460 struct hlist_head *rl;
461 struct hlist_node *next;
462 struct dev_rcv_lists *d;
463
464 spin_lock(&can_rcvlists_lock);
465
466 d = find_dev_rcv_lists(dev);
467 if (!d) {
468 printk(KERN_ERR "BUG: receive list not found for "
469 "dev %s, id %03X, mask %03X\n",
470 DNAME(dev), can_id, mask);
471 goto out;
472 }
473
474 rl = find_rcv_list(&can_id, &mask, d);
475
476 /*
477 * Search the receiver list for the item to delete. This should
478 * exist, since no receiver may be unregistered that hasn't
479 * been registered before.
480 */
481
482 hlist_for_each_entry_rcu(r, next, rl, list) {
483 if (r->can_id == can_id && r->mask == mask
484 && r->func == func && r->data == data)
485 break;
486 }
487
488 /*
489 * Check for bugs in CAN protocol implementations:
490 * If no matching list item was found, the list cursor variable next
491 * will be NULL, while r will point to the last item of the list.
492 */
493
494 if (!next) {
495 printk(KERN_ERR "BUG: receive list entry not found for "
496 "dev %s, id %03X, mask %03X\n",
497 DNAME(dev), can_id, mask);
498 r = NULL;
499 d = NULL;
500 goto out;
501 }
502
503 hlist_del_rcu(&r->list);
504 d->entries--;
505
506 if (can_pstats.rcv_entries > 0)
507 can_pstats.rcv_entries--;
508
509 /* remove device structure requested by NETDEV_UNREGISTER */
510 if (d->remove_on_zero_entries && !d->entries)
511 hlist_del_rcu(&d->list);
512 else
513 d = NULL;
514
515 out:
516 spin_unlock(&can_rcvlists_lock);
517
518 /* schedule the receiver item for deletion */
519 if (r)
520 call_rcu(&r->rcu, can_rx_delete_receiver);
521
522 /* schedule the device structure for deletion */
523 if (d)
524 call_rcu(&d->rcu, can_rx_delete_device);
525}
526EXPORT_SYMBOL(can_rx_unregister);
527
528static inline void deliver(struct sk_buff *skb, struct receiver *r)
529{
530 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
531
532 if (clone) {
533 clone->sk = skb->sk;
534 r->func(clone, r->data);
535 r->matches++;
536 }
537}
538
539static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb)
540{
541 struct receiver *r;
542 struct hlist_node *n;
543 int matches = 0;
544 struct can_frame *cf = (struct can_frame *)skb->data;
545 canid_t can_id = cf->can_id;
546
547 if (d->entries == 0)
548 return 0;
549
550 if (can_id & CAN_ERR_FLAG) {
551 /* check for error frame entries only */
552 hlist_for_each_entry_rcu(r, n, &d->rx[RX_ERR], list) {
553 if (can_id & r->mask) {
554 deliver(skb, r);
555 matches++;
556 }
557 }
558 return matches;
559 }
560
561 /* check for unfiltered entries */
562 hlist_for_each_entry_rcu(r, n, &d->rx[RX_ALL], list) {
563 deliver(skb, r);
564 matches++;
565 }
566
567 /* check for can_id/mask entries */
568 hlist_for_each_entry_rcu(r, n, &d->rx[RX_FIL], list) {
569 if ((can_id & r->mask) == r->can_id) {
570 deliver(skb, r);
571 matches++;
572 }
573 }
574
575 /* check for inverted can_id/mask entries */
576 hlist_for_each_entry_rcu(r, n, &d->rx[RX_INV], list) {
577 if ((can_id & r->mask) != r->can_id) {
578 deliver(skb, r);
579 matches++;
580 }
581 }
582
583 /* check CAN_ID specific entries */
584 if (can_id & CAN_EFF_FLAG) {
585 hlist_for_each_entry_rcu(r, n, &d->rx[RX_EFF], list) {
586 if (r->can_id == can_id) {
587 deliver(skb, r);
588 matches++;
589 }
590 }
591 } else {
592 can_id &= CAN_SFF_MASK;
593 hlist_for_each_entry_rcu(r, n, &d->rx_sff[can_id], list) {
594 deliver(skb, r);
595 matches++;
596 }
597 }
598
599 return matches;
600}
601
602static int can_rcv(struct sk_buff *skb, struct net_device *dev,
603 struct packet_type *pt, struct net_device *orig_dev)
604{
605 struct dev_rcv_lists *d;
606 int matches;
607
608 if (dev->type != ARPHRD_CAN || dev->nd_net != &init_net) {
609 kfree_skb(skb);
610 return 0;
611 }
612
613 /* update statistics */
614 can_stats.rx_frames++;
615 can_stats.rx_frames_delta++;
616
617 rcu_read_lock();
618
619 /* deliver the packet to sockets listening on all devices */
620 matches = can_rcv_filter(&can_rx_alldev_list, skb);
621
622 /* find receive list for this device */
623 d = find_dev_rcv_lists(dev);
624 if (d)
625 matches += can_rcv_filter(d, skb);
626
627 rcu_read_unlock();
628
629 /* free the skbuff allocated by the netdevice driver */
630 kfree_skb(skb);
631
632 if (matches > 0) {
633 can_stats.matches++;
634 can_stats.matches_delta++;
635 }
636
637 return 0;
638}
639
640/*
641 * af_can protocol functions
642 */
643
644/**
645 * can_proto_register - register CAN transport protocol
646 * @cp: pointer to CAN protocol structure
647 *
648 * Return:
649 * 0 on success
650 * -EINVAL invalid (out of range) protocol number
651 * -EBUSY protocol already in use
652 * -ENOBUF if proto_register() fails
653 */
654int can_proto_register(struct can_proto *cp)
655{
656 int proto = cp->protocol;
657 int err = 0;
658
659 if (proto < 0 || proto >= CAN_NPROTO) {
660 printk(KERN_ERR "can: protocol number %d out of range\n",
661 proto);
662 return -EINVAL;
663 }
664
665 spin_lock(&proto_tab_lock);
666 if (proto_tab[proto]) {
667 printk(KERN_ERR "can: protocol %d already registered\n",
668 proto);
669 err = -EBUSY;
670 goto errout;
671 }
672
673 err = proto_register(cp->prot, 0);
674 if (err < 0)
675 goto errout;
676
677 proto_tab[proto] = cp;
678
679 /* use generic ioctl function if the module doesn't bring its own */
680 if (!cp->ops->ioctl)
681 cp->ops->ioctl = can_ioctl;
682
683 errout:
684 spin_unlock(&proto_tab_lock);
685
686 return err;
687}
688EXPORT_SYMBOL(can_proto_register);
689
690/**
691 * can_proto_unregister - unregister CAN transport protocol
692 * @cp: pointer to CAN protocol structure
693 */
694void can_proto_unregister(struct can_proto *cp)
695{
696 int proto = cp->protocol;
697
698 spin_lock(&proto_tab_lock);
699 if (!proto_tab[proto]) {
700 printk(KERN_ERR "BUG: can: protocol %d is not registered\n",
701 proto);
702 }
703 proto_unregister(cp->prot);
704 proto_tab[proto] = NULL;
705 spin_unlock(&proto_tab_lock);
706}
707EXPORT_SYMBOL(can_proto_unregister);
708
709/*
710 * af_can notifier to create/remove CAN netdevice specific structs
711 */
712static int can_notifier(struct notifier_block *nb, unsigned long msg,
713 void *data)
714{
715 struct net_device *dev = (struct net_device *)data;
716 struct dev_rcv_lists *d;
717
718 if (dev->nd_net != &init_net)
719 return NOTIFY_DONE;
720
721 if (dev->type != ARPHRD_CAN)
722 return NOTIFY_DONE;
723
724 switch (msg) {
725
726 case NETDEV_REGISTER:
727
728 /*
729 * create new dev_rcv_lists for this device
730 *
731 * N.B. zeroing the struct is the correct initialization
732 * for the embedded hlist_head structs.
733 * Another list type, e.g. list_head, would require
734 * explicit initialization.
735 */
736
737 d = kzalloc(sizeof(*d), GFP_KERNEL);
738 if (!d) {
739 printk(KERN_ERR
740 "can: allocation of receive list failed\n");
741 return NOTIFY_DONE;
742 }
743 d->dev = dev;
744
745 spin_lock(&can_rcvlists_lock);
746 hlist_add_head_rcu(&d->list, &can_rx_dev_list);
747 spin_unlock(&can_rcvlists_lock);
748
749 break;
750
751 case NETDEV_UNREGISTER:
752 spin_lock(&can_rcvlists_lock);
753
754 d = find_dev_rcv_lists(dev);
755 if (d) {
756 if (d->entries) {
757 d->remove_on_zero_entries = 1;
758 d = NULL;
759 } else
760 hlist_del_rcu(&d->list);
761 } else
762 printk(KERN_ERR "can: notifier: receive list not "
763 "found for dev %s\n", dev->name);
764
765 spin_unlock(&can_rcvlists_lock);
766
767 if (d)
768 call_rcu(&d->rcu, can_rx_delete_device);
769
770 break;
771 }
772
773 return NOTIFY_DONE;
774}
775
776/*
777 * af_can module init/exit functions
778 */
779
780static struct packet_type can_packet __read_mostly = {
781 .type = __constant_htons(ETH_P_CAN),
782 .dev = NULL,
783 .func = can_rcv,
784};
785
786static struct net_proto_family can_family_ops __read_mostly = {
787 .family = PF_CAN,
788 .create = can_create,
789 .owner = THIS_MODULE,
790};
791
792/* notifier block for netdevice event */
793static struct notifier_block can_netdev_notifier __read_mostly = {
794 .notifier_call = can_notifier,
795};
796
797static __init int can_init(void)
798{
799 printk(banner);
800
801 rcv_cache = kmem_cache_create("can_receiver", sizeof(struct receiver),
802 0, 0, NULL);
803 if (!rcv_cache)
804 return -ENOMEM;
805
806 /*
807 * Insert can_rx_alldev_list for reception on all devices.
808 * This struct is zero initialized which is correct for the
809 * embedded hlist heads, the dev pointer, and the entries counter.
810 */
811
812 spin_lock(&can_rcvlists_lock);
813 hlist_add_head_rcu(&can_rx_alldev_list.list, &can_rx_dev_list);
814 spin_unlock(&can_rcvlists_lock);
815
816 if (stats_timer) {
817 /* the statistics are updated every second (timer triggered) */
818 setup_timer(&can_stattimer, can_stat_update, 0);
819 mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
820 } else
821 can_stattimer.function = NULL;
822
823 can_init_proc();
824
825 /* protocol register */
826 sock_register(&can_family_ops);
827 register_netdevice_notifier(&can_netdev_notifier);
828 dev_add_pack(&can_packet);
829
830 return 0;
831}
832
833static __exit void can_exit(void)
834{
835 struct dev_rcv_lists *d;
836 struct hlist_node *n, *next;
837
838 if (stats_timer)
839 del_timer(&can_stattimer);
840
841 can_remove_proc();
842
843 /* protocol unregister */
844 dev_remove_pack(&can_packet);
845 unregister_netdevice_notifier(&can_netdev_notifier);
846 sock_unregister(PF_CAN);
847
848 /* remove can_rx_dev_list */
849 spin_lock(&can_rcvlists_lock);
850 hlist_del(&can_rx_alldev_list.list);
851 hlist_for_each_entry_safe(d, n, next, &can_rx_dev_list, list) {
852 hlist_del(&d->list);
853 kfree(d);
854 }
855 spin_unlock(&can_rcvlists_lock);
856
857 kmem_cache_destroy(rcv_cache);
858}
859
860module_init(can_init);
861module_exit(can_exit);
diff --git a/net/can/af_can.h b/net/can/af_can.h
new file mode 100644
index 000000000000..18f91e37cc30
--- /dev/null
+++ b/net/can/af_can.h
@@ -0,0 +1,122 @@
1/*
2 * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Volkswagen nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * Alternatively, provided that this notice is retained in full, this
18 * software may be distributed under the terms of the GNU General
19 * Public License ("GPL") version 2, in which case the provisions of the
20 * GPL apply INSTEAD OF those given above.
21 *
22 * The provided data structures and external interfaces from this code
23 * are not restricted to be used by modules with a GPL compatible license.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
36 * DAMAGE.
37 *
38 * Send feedback to <socketcan-users@lists.berlios.de>
39 *
40 */
41
42#ifndef AF_CAN_H
43#define AF_CAN_H
44
45#include <linux/skbuff.h>
46#include <linux/netdevice.h>
47#include <linux/list.h>
48#include <linux/rcupdate.h>
49#include <linux/can.h>
50
51/* af_can rx dispatcher structures */
52
53struct receiver {
54 struct hlist_node list;
55 struct rcu_head rcu;
56 canid_t can_id;
57 canid_t mask;
58 unsigned long matches;
59 void (*func)(struct sk_buff *, void *);
60 void *data;
61 char *ident;
62};
63
64enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_EFF, RX_MAX };
65
66struct dev_rcv_lists {
67 struct hlist_node list;
68 struct rcu_head rcu;
69 struct net_device *dev;
70 struct hlist_head rx[RX_MAX];
71 struct hlist_head rx_sff[0x800];
72 int remove_on_zero_entries;
73 int entries;
74};
75
76/* statistic structures */
77
78/* can be reset e.g. by can_init_stats() */
79struct s_stats {
80 unsigned long jiffies_init;
81
82 unsigned long rx_frames;
83 unsigned long tx_frames;
84 unsigned long matches;
85
86 unsigned long total_rx_rate;
87 unsigned long total_tx_rate;
88 unsigned long total_rx_match_ratio;
89
90 unsigned long current_rx_rate;
91 unsigned long current_tx_rate;
92 unsigned long current_rx_match_ratio;
93
94 unsigned long max_rx_rate;
95 unsigned long max_tx_rate;
96 unsigned long max_rx_match_ratio;
97
98 unsigned long rx_frames_delta;
99 unsigned long tx_frames_delta;
100 unsigned long matches_delta;
101};
102
103/* persistent statistics */
104struct s_pstats {
105 unsigned long stats_reset;
106 unsigned long user_reset;
107 unsigned long rcv_entries;
108 unsigned long rcv_entries_max;
109};
110
111/* function prototypes for the CAN networklayer procfs (proc.c) */
112extern void can_init_proc(void);
113extern void can_remove_proc(void);
114extern void can_stat_update(unsigned long data);
115
116/* structures and variables from af_can.c needed in proc.c for reading */
117extern struct timer_list can_stattimer; /* timer for statistics update */
118extern struct s_stats can_stats; /* packet statistics */
119extern struct s_pstats can_pstats; /* receive list statistics */
120extern struct hlist_head can_rx_dev_list; /* rx dispatcher structures */
121
122#endif /* AF_CAN_H */
diff --git a/net/can/proc.c b/net/can/proc.c
new file mode 100644
index 000000000000..520fef5e5398
--- /dev/null
+++ b/net/can/proc.c
@@ -0,0 +1,533 @@
1/*
2 * proc.c - procfs support for Protocol family CAN core module
3 *
4 * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Volkswagen nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * Alternatively, provided that this notice is retained in full, this
20 * software may be distributed under the terms of the GNU General
21 * Public License ("GPL") version 2, in which case the provisions of the
22 * GPL apply INSTEAD OF those given above.
23 *
24 * The provided data structures and external interfaces from this code
25 * are not restricted to be used by modules with a GPL compatible license.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38 * DAMAGE.
39 *
40 * Send feedback to <socketcan-users@lists.berlios.de>
41 *
42 */
43
44#include <linux/module.h>
45#include <linux/proc_fs.h>
46#include <linux/list.h>
47#include <linux/rcupdate.h>
48#include <linux/can/core.h>
49
50#include "af_can.h"
51
52/*
53 * proc filenames for the PF_CAN core
54 */
55
56#define CAN_PROC_VERSION "version"
57#define CAN_PROC_STATS "stats"
58#define CAN_PROC_RESET_STATS "reset_stats"
59#define CAN_PROC_RCVLIST_ALL "rcvlist_all"
60#define CAN_PROC_RCVLIST_FIL "rcvlist_fil"
61#define CAN_PROC_RCVLIST_INV "rcvlist_inv"
62#define CAN_PROC_RCVLIST_SFF "rcvlist_sff"
63#define CAN_PROC_RCVLIST_EFF "rcvlist_eff"
64#define CAN_PROC_RCVLIST_ERR "rcvlist_err"
65
66static struct proc_dir_entry *can_dir;
67static struct proc_dir_entry *pde_version;
68static struct proc_dir_entry *pde_stats;
69static struct proc_dir_entry *pde_reset_stats;
70static struct proc_dir_entry *pde_rcvlist_all;
71static struct proc_dir_entry *pde_rcvlist_fil;
72static struct proc_dir_entry *pde_rcvlist_inv;
73static struct proc_dir_entry *pde_rcvlist_sff;
74static struct proc_dir_entry *pde_rcvlist_eff;
75static struct proc_dir_entry *pde_rcvlist_err;
76
77static int user_reset;
78
79static const char rx_list_name[][8] = {
80 [RX_ERR] = "rx_err",
81 [RX_ALL] = "rx_all",
82 [RX_FIL] = "rx_fil",
83 [RX_INV] = "rx_inv",
84 [RX_EFF] = "rx_eff",
85};
86
87/*
88 * af_can statistics stuff
89 */
90
91static void can_init_stats(void)
92{
93 /*
94 * This memset function is called from a timer context (when
95 * can_stattimer is active which is the default) OR in a process
96 * context (reading the proc_fs when can_stattimer is disabled).
97 */
98 memset(&can_stats, 0, sizeof(can_stats));
99 can_stats.jiffies_init = jiffies;
100
101 can_pstats.stats_reset++;
102
103 if (user_reset) {
104 user_reset = 0;
105 can_pstats.user_reset++;
106 }
107}
108
109static unsigned long calc_rate(unsigned long oldjif, unsigned long newjif,
110 unsigned long count)
111{
112 unsigned long rate;
113
114 if (oldjif == newjif)
115 return 0;
116
117 /* see can_stat_update() - this should NEVER happen! */
118 if (count > (ULONG_MAX / HZ)) {
119 printk(KERN_ERR "can: calc_rate: count exceeded! %ld\n",
120 count);
121 return 99999999;
122 }
123
124 rate = (count * HZ) / (newjif - oldjif);
125
126 return rate;
127}
128
129void can_stat_update(unsigned long data)
130{
131 unsigned long j = jiffies; /* snapshot */
132
133 /* restart counting in timer context on user request */
134 if (user_reset)
135 can_init_stats();
136
137 /* restart counting on jiffies overflow */
138 if (j < can_stats.jiffies_init)
139 can_init_stats();
140
141 /* prevent overflow in calc_rate() */
142 if (can_stats.rx_frames > (ULONG_MAX / HZ))
143 can_init_stats();
144
145 /* prevent overflow in calc_rate() */
146 if (can_stats.tx_frames > (ULONG_MAX / HZ))
147 can_init_stats();
148
149 /* matches overflow - very improbable */
150 if (can_stats.matches > (ULONG_MAX / 100))
151 can_init_stats();
152
153 /* calc total values */
154 if (can_stats.rx_frames)
155 can_stats.total_rx_match_ratio = (can_stats.matches * 100) /
156 can_stats.rx_frames;
157
158 can_stats.total_tx_rate = calc_rate(can_stats.jiffies_init, j,
159 can_stats.tx_frames);
160 can_stats.total_rx_rate = calc_rate(can_stats.jiffies_init, j,
161 can_stats.rx_frames);
162
163 /* calc current values */
164 if (can_stats.rx_frames_delta)
165 can_stats.current_rx_match_ratio =
166 (can_stats.matches_delta * 100) /
167 can_stats.rx_frames_delta;
168
169 can_stats.current_tx_rate = calc_rate(0, HZ, can_stats.tx_frames_delta);
170 can_stats.current_rx_rate = calc_rate(0, HZ, can_stats.rx_frames_delta);
171
172 /* check / update maximum values */
173 if (can_stats.max_tx_rate < can_stats.current_tx_rate)
174 can_stats.max_tx_rate = can_stats.current_tx_rate;
175
176 if (can_stats.max_rx_rate < can_stats.current_rx_rate)
177 can_stats.max_rx_rate = can_stats.current_rx_rate;
178
179 if (can_stats.max_rx_match_ratio < can_stats.current_rx_match_ratio)
180 can_stats.max_rx_match_ratio = can_stats.current_rx_match_ratio;
181
182 /* clear values for 'current rate' calculation */
183 can_stats.tx_frames_delta = 0;
184 can_stats.rx_frames_delta = 0;
185 can_stats.matches_delta = 0;
186
187 /* restart timer (one second) */
188 mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
189}
190
191/*
192 * proc read functions
193 *
194 * From known use-cases we expect about 10 entries in a receive list to be
195 * printed in the proc_fs. So PAGE_SIZE is definitely enough space here.
196 *
197 */
198
199static int can_print_rcvlist(char *page, int len, struct hlist_head *rx_list,
200 struct net_device *dev)
201{
202 struct receiver *r;
203 struct hlist_node *n;
204
205 rcu_read_lock();
206 hlist_for_each_entry_rcu(r, n, rx_list, list) {
207 char *fmt = (r->can_id & CAN_EFF_FLAG)?
208 " %-5s %08X %08x %08x %08x %8ld %s\n" :
209 " %-5s %03X %08x %08lx %08lx %8ld %s\n";
210
211 len += snprintf(page + len, PAGE_SIZE - len, fmt,
212 DNAME(dev), r->can_id, r->mask,
213 (unsigned long)r->func, (unsigned long)r->data,
214 r->matches, r->ident);
215
216 /* does a typical line fit into the current buffer? */
217
218 /* 100 Bytes before end of buffer */
219 if (len > PAGE_SIZE - 100) {
220 /* mark output cut off */
221 len += snprintf(page + len, PAGE_SIZE - len,
222 " (..)\n");
223 break;
224 }
225 }
226 rcu_read_unlock();
227
228 return len;
229}
230
231static int can_print_recv_banner(char *page, int len)
232{
233 /*
234 * can1. 00000000 00000000 00000000
235 * ....... 0 tp20
236 */
237 len += snprintf(page + len, PAGE_SIZE - len,
238 " device can_id can_mask function"
239 " userdata matches ident\n");
240
241 return len;
242}
243
244static int can_proc_read_stats(char *page, char **start, off_t off,
245 int count, int *eof, void *data)
246{
247 int len = 0;
248
249 len += snprintf(page + len, PAGE_SIZE - len, "\n");
250 len += snprintf(page + len, PAGE_SIZE - len,
251 " %8ld transmitted frames (TXF)\n",
252 can_stats.tx_frames);
253 len += snprintf(page + len, PAGE_SIZE - len,
254 " %8ld received frames (RXF)\n", can_stats.rx_frames);
255 len += snprintf(page + len, PAGE_SIZE - len,
256 " %8ld matched frames (RXMF)\n", can_stats.matches);
257
258 len += snprintf(page + len, PAGE_SIZE - len, "\n");
259
260 if (can_stattimer.function == can_stat_update) {
261 len += snprintf(page + len, PAGE_SIZE - len,
262 " %8ld %% total match ratio (RXMR)\n",
263 can_stats.total_rx_match_ratio);
264
265 len += snprintf(page + len, PAGE_SIZE - len,
266 " %8ld frames/s total tx rate (TXR)\n",
267 can_stats.total_tx_rate);
268 len += snprintf(page + len, PAGE_SIZE - len,
269 " %8ld frames/s total rx rate (RXR)\n",
270 can_stats.total_rx_rate);
271
272 len += snprintf(page + len, PAGE_SIZE - len, "\n");
273
274 len += snprintf(page + len, PAGE_SIZE - len,
275 " %8ld %% current match ratio (CRXMR)\n",
276 can_stats.current_rx_match_ratio);
277
278 len += snprintf(page + len, PAGE_SIZE - len,
279 " %8ld frames/s current tx rate (CTXR)\n",
280 can_stats.current_tx_rate);
281 len += snprintf(page + len, PAGE_SIZE - len,
282 " %8ld frames/s current rx rate (CRXR)\n",
283 can_stats.current_rx_rate);
284
285 len += snprintf(page + len, PAGE_SIZE - len, "\n");
286
287 len += snprintf(page + len, PAGE_SIZE - len,
288 " %8ld %% max match ratio (MRXMR)\n",
289 can_stats.max_rx_match_ratio);
290
291 len += snprintf(page + len, PAGE_SIZE - len,
292 " %8ld frames/s max tx rate (MTXR)\n",
293 can_stats.max_tx_rate);
294 len += snprintf(page + len, PAGE_SIZE - len,
295 " %8ld frames/s max rx rate (MRXR)\n",
296 can_stats.max_rx_rate);
297
298 len += snprintf(page + len, PAGE_SIZE - len, "\n");
299 }
300
301 len += snprintf(page + len, PAGE_SIZE - len,
302 " %8ld current receive list entries (CRCV)\n",
303 can_pstats.rcv_entries);
304 len += snprintf(page + len, PAGE_SIZE - len,
305 " %8ld maximum receive list entries (MRCV)\n",
306 can_pstats.rcv_entries_max);
307
308 if (can_pstats.stats_reset)
309 len += snprintf(page + len, PAGE_SIZE - len,
310 "\n %8ld statistic resets (STR)\n",
311 can_pstats.stats_reset);
312
313 if (can_pstats.user_reset)
314 len += snprintf(page + len, PAGE_SIZE - len,
315 " %8ld user statistic resets (USTR)\n",
316 can_pstats.user_reset);
317
318 len += snprintf(page + len, PAGE_SIZE - len, "\n");
319
320 *eof = 1;
321 return len;
322}
323
324static int can_proc_read_reset_stats(char *page, char **start, off_t off,
325 int count, int *eof, void *data)
326{
327 int len = 0;
328
329 user_reset = 1;
330
331 if (can_stattimer.function == can_stat_update) {
332 len += snprintf(page + len, PAGE_SIZE - len,
333 "Scheduled statistic reset #%ld.\n",
334 can_pstats.stats_reset + 1);
335
336 } else {
337 if (can_stats.jiffies_init != jiffies)
338 can_init_stats();
339
340 len += snprintf(page + len, PAGE_SIZE - len,
341 "Performed statistic reset #%ld.\n",
342 can_pstats.stats_reset);
343 }
344
345 *eof = 1;
346 return len;
347}
348
349static int can_proc_read_version(char *page, char **start, off_t off,
350 int count, int *eof, void *data)
351{
352 int len = 0;
353
354 len += snprintf(page + len, PAGE_SIZE - len, "%s\n",
355 CAN_VERSION_STRING);
356 *eof = 1;
357 return len;
358}
359
360static int can_proc_read_rcvlist(char *page, char **start, off_t off,
361 int count, int *eof, void *data)
362{
363 /* double cast to prevent GCC warning */
364 int idx = (int)(long)data;
365 int len = 0;
366 struct dev_rcv_lists *d;
367 struct hlist_node *n;
368
369 len += snprintf(page + len, PAGE_SIZE - len,
370 "\nreceive list '%s':\n", rx_list_name[idx]);
371
372 rcu_read_lock();
373 hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
374
375 if (!hlist_empty(&d->rx[idx])) {
376 len = can_print_recv_banner(page, len);
377 len = can_print_rcvlist(page, len, &d->rx[idx], d->dev);
378 } else
379 len += snprintf(page + len, PAGE_SIZE - len,
380 " (%s: no entry)\n", DNAME(d->dev));
381
382 /* exit on end of buffer? */
383 if (len > PAGE_SIZE - 100)
384 break;
385 }
386 rcu_read_unlock();
387
388 len += snprintf(page + len, PAGE_SIZE - len, "\n");
389
390 *eof = 1;
391 return len;
392}
393
394static int can_proc_read_rcvlist_sff(char *page, char **start, off_t off,
395 int count, int *eof, void *data)
396{
397 int len = 0;
398 struct dev_rcv_lists *d;
399 struct hlist_node *n;
400
401 /* RX_SFF */
402 len += snprintf(page + len, PAGE_SIZE - len,
403 "\nreceive list 'rx_sff':\n");
404
405 rcu_read_lock();
406 hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
407 int i, all_empty = 1;
408 /* check wether at least one list is non-empty */
409 for (i = 0; i < 0x800; i++)
410 if (!hlist_empty(&d->rx_sff[i])) {
411 all_empty = 0;
412 break;
413 }
414
415 if (!all_empty) {
416 len = can_print_recv_banner(page, len);
417 for (i = 0; i < 0x800; i++) {
418 if (!hlist_empty(&d->rx_sff[i]) &&
419 len < PAGE_SIZE - 100)
420 len = can_print_rcvlist(page, len,
421 &d->rx_sff[i],
422 d->dev);
423 }
424 } else
425 len += snprintf(page + len, PAGE_SIZE - len,
426 " (%s: no entry)\n", DNAME(d->dev));
427
428 /* exit on end of buffer? */
429 if (len > PAGE_SIZE - 100)
430 break;
431 }
432 rcu_read_unlock();
433
434 len += snprintf(page + len, PAGE_SIZE - len, "\n");
435
436 *eof = 1;
437 return len;
438}
439
440/*
441 * proc utility functions
442 */
443
444static struct proc_dir_entry *can_create_proc_readentry(const char *name,
445 mode_t mode,
446 read_proc_t *read_proc,
447 void *data)
448{
449 if (can_dir)
450 return create_proc_read_entry(name, mode, can_dir, read_proc,
451 data);
452 else
453 return NULL;
454}
455
456static void can_remove_proc_readentry(const char *name)
457{
458 if (can_dir)
459 remove_proc_entry(name, can_dir);
460}
461
462/*
463 * can_init_proc - create main CAN proc directory and procfs entries
464 */
465void can_init_proc(void)
466{
467 /* create /proc/net/can directory */
468 can_dir = proc_mkdir("can", init_net.proc_net);
469
470 if (!can_dir) {
471 printk(KERN_INFO "can: failed to create /proc/net/can . "
472 "CONFIG_PROC_FS missing?\n");
473 return;
474 }
475
476 can_dir->owner = THIS_MODULE;
477
478 /* own procfs entries from the AF_CAN core */
479 pde_version = can_create_proc_readentry(CAN_PROC_VERSION, 0644,
480 can_proc_read_version, NULL);
481 pde_stats = can_create_proc_readentry(CAN_PROC_STATS, 0644,
482 can_proc_read_stats, NULL);
483 pde_reset_stats = can_create_proc_readentry(CAN_PROC_RESET_STATS, 0644,
484 can_proc_read_reset_stats, NULL);
485 pde_rcvlist_err = can_create_proc_readentry(CAN_PROC_RCVLIST_ERR, 0644,
486 can_proc_read_rcvlist, (void *)RX_ERR);
487 pde_rcvlist_all = can_create_proc_readentry(CAN_PROC_RCVLIST_ALL, 0644,
488 can_proc_read_rcvlist, (void *)RX_ALL);
489 pde_rcvlist_fil = can_create_proc_readentry(CAN_PROC_RCVLIST_FIL, 0644,
490 can_proc_read_rcvlist, (void *)RX_FIL);
491 pde_rcvlist_inv = can_create_proc_readentry(CAN_PROC_RCVLIST_INV, 0644,
492 can_proc_read_rcvlist, (void *)RX_INV);
493 pde_rcvlist_eff = can_create_proc_readentry(CAN_PROC_RCVLIST_EFF, 0644,
494 can_proc_read_rcvlist, (void *)RX_EFF);
495 pde_rcvlist_sff = can_create_proc_readentry(CAN_PROC_RCVLIST_SFF, 0644,
496 can_proc_read_rcvlist_sff, NULL);
497}
498
499/*
500 * can_remove_proc - remove procfs entries and main CAN proc directory
501 */
502void can_remove_proc(void)
503{
504 if (pde_version)
505 can_remove_proc_readentry(CAN_PROC_VERSION);
506
507 if (pde_stats)
508 can_remove_proc_readentry(CAN_PROC_STATS);
509
510 if (pde_reset_stats)
511 can_remove_proc_readentry(CAN_PROC_RESET_STATS);
512
513 if (pde_rcvlist_err)
514 can_remove_proc_readentry(CAN_PROC_RCVLIST_ERR);
515
516 if (pde_rcvlist_all)
517 can_remove_proc_readentry(CAN_PROC_RCVLIST_ALL);
518
519 if (pde_rcvlist_fil)
520 can_remove_proc_readentry(CAN_PROC_RCVLIST_FIL);
521
522 if (pde_rcvlist_inv)
523 can_remove_proc_readentry(CAN_PROC_RCVLIST_INV);
524
525 if (pde_rcvlist_eff)
526 can_remove_proc_readentry(CAN_PROC_RCVLIST_EFF);
527
528 if (pde_rcvlist_sff)
529 can_remove_proc_readentry(CAN_PROC_RCVLIST_SFF);
530
531 if (can_dir)
532 proc_net_remove(&init_net, "can");
533}