]> rtime.felk.cvut.cz Git - socketcan-devel.git/blob - kernel/2.6/drivers/net/can/vcan.c
Reformated to meet Linux Documentation/Codingstyle (e.g. 80 chars/Line).
[socketcan-devel.git] / kernel / 2.6 / drivers / net / can / vcan.c
1 /*
2  * vcan.c - Virtual CAN interface
3  *
4  * Copyright (c) 2002-2005 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, the following disclaimer and
12  *    the referenced file 'COPYING'.
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 as distributed in the 'COPYING'
23  * file from the main directory of the linux kernel source.
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/autoconf.h>
46 #include <linux/module.h>
47 #include <linux/init.h>
48 #include <linux/netdevice.h>
49 #include <linux/if_arp.h>
50 #include <linux/if_ether.h>
51
52 #include <linux/can.h>
53 #include <linux/can/version.h>
54
55 RCSID("$Id$");
56
57 static __initdata const char banner[] = KERN_INFO "CAN: virtual CAN "
58                                         "interface " VERSION "\n"; 
59
60 MODULE_DESCRIPTION("virtual CAN interface");
61 MODULE_LICENSE("Dual BSD/GPL");
62 MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
63
64 #ifdef CONFIG_CAN_DEBUG_DEVICES
65 static int debug = 0;
66 module_param(debug, int, S_IRUGO);
67 #define DBG(args...)       (debug & 1 ? \
68                                (printk(KERN_DEBUG "VCAN %s: ", __func__), \
69                                 printk(args)) : 0)
70 #define DBG_FRAME(args...) (debug & 2 ? can_debug_cframe(args) : 0)
71 #define DBG_SKB(skb)       (debug & 4 ? can_debug_skb(skb) : 0)
72 #else
73 #define DBG(args...)
74 #define DBG_FRAME(args...)
75 #define DBG_SKB(skb)
76 #endif
77
78 /* Indicate if this VCAN driver should do a real loopback, or if this */
79 /* should be done in af_can.c */
80 #undef  DO_LOOPBACK
81
82 #define STATSIZE sizeof(struct net_device_stats)
83
84 static int numdev = 4; /* default number of virtual CAN interfaces */
85 module_param(numdev, int, S_IRUGO);
86 MODULE_PARM_DESC(numdev, "Number of virtual CAN devices");
87
88 static struct net_device **vcan_devs; /* root pointer to netdevice structs */
89
90 static int vcan_open(struct net_device *dev)
91 {
92         DBG("%s: interface up\n", dev->name);
93
94         netif_start_queue(dev);
95         return 0;
96 }
97
98 static int vcan_stop(struct net_device *dev)
99 {
100         DBG("%s: interface down\n", dev->name);
101
102         netif_stop_queue(dev);
103         return 0;
104 }
105
106 #ifdef DO_LOOPBACK
107
108 static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
109 {
110         struct net_device_stats *stats = netdev_priv(dev);
111         stats->rx_packets++;
112         stats->rx_bytes += skb->len;
113
114         skb->protocol  = htons(ETH_P_CAN);
115         skb->dev       = dev;
116         skb->ip_summed = CHECKSUM_UNNECESSARY;
117
118         DBG("received skbuff on interface %d\n", dev->ifindex);
119         DBG_SKB(skb);
120
121         netif_rx(skb);
122 }
123
124 #endif
125
126 static int vcan_tx(struct sk_buff *skb, struct net_device *dev)
127 {
128         struct net_device_stats *stats = netdev_priv(dev);
129         int loop;
130
131         DBG("sending skbuff on interface %s\n", dev->name);
132         DBG_SKB(skb);
133         DBG_FRAME("VCAN: transmit CAN frame", (struct can_frame *)skb->data);
134
135         stats->tx_packets++;
136         stats->tx_bytes += skb->len;
137
138         loop = *(struct sock **)skb->cb != NULL;   /* loopback required */
139
140 #ifdef DO_LOOPBACK
141         if (loop) {
142                 if (atomic_read(&skb->users) != 1) {
143                         struct sk_buff *old_skb = skb;
144                         skb = skb_clone(old_skb, GFP_ATOMIC);
145                         DBG("  freeing old skbuff %p, using new skbuff %p\n",
146                             old_skb, skb);
147                         kfree_skb(old_skb);
148                         if (!skb) {
149                                 return 0;
150                         }
151                 } else
152                         skb_orphan(skb);
153
154                 vcan_rx(skb, dev); /* with packet counting */
155         } else {
156                 /* no looped packets => no counting */
157                 kfree_skb(skb);
158         }
159 #else
160         /* only count, when the CAN core did a loopback */
161         if (loop) {
162                 stats->rx_packets++;
163                 stats->rx_bytes += skb->len;
164         }
165         kfree_skb(skb);
166 #endif
167         return 0;
168 }
169
170 static int vcan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
171 {
172         return -EOPNOTSUPP;
173 }
174
175 static int vcan_rebuild_header(struct sk_buff *skb)
176 {
177         DBG("skbuff %p\n", skb);
178         DBG_SKB(skb);
179         return 0;
180 }
181
182 static int vcan_header(struct sk_buff *skb, struct net_device *dev,
183                        unsigned short type, void *daddr, void *saddr,
184                        unsigned int len)
185 {
186         DBG("skbuff %p, device %p\n", skb, dev);
187         DBG_SKB(skb);
188         return 0;
189 }
190
191
192 static struct net_device_stats *vcan_get_stats(struct net_device *dev)
193 {
194         struct net_device_stats *stats = netdev_priv(dev);
195         return stats;
196 }
197
198 static void vcan_init(struct net_device *dev)
199 {
200         DBG("dev %s\n", dev->name);
201
202         ether_setup(dev);
203
204         memset(dev->priv, 0, STATSIZE);
205
206         dev->type              = ARPHRD_CAN;
207         dev->mtu               = sizeof(struct can_frame);
208         dev->flags             = IFF_NOARP;
209 #ifdef DO_LOOPBACK
210         dev->flags            |= IFF_LOOPBACK;
211 #endif
212
213         dev->open              = vcan_open;
214         dev->stop              = vcan_stop;
215         dev->set_config        = NULL;
216         dev->hard_start_xmit   = vcan_tx;
217         dev->do_ioctl          = vcan_ioctl;
218         dev->get_stats         = vcan_get_stats;
219         dev->hard_header       = vcan_header;
220         dev->rebuild_header    = vcan_rebuild_header;
221         dev->hard_header_cache = NULL;
222
223         SET_MODULE_OWNER(dev);
224 }
225
226 static __init int vcan_init_module(void)
227 {
228         int i, ndev = 0, result = 0;
229
230         printk(banner);
231
232         if (numdev < 1)
233                 numdev = 1; /* register at least one interface */
234
235         printk(KERN_INFO "vcan: registering %d virtual CAN interfaces.\n",
236                numdev );
237
238         vcan_devs = kmalloc(numdev * sizeof(struct net_device *), GFP_KERNEL);
239         if (!vcan_devs) {
240                 printk(KERN_ERR "vcan: Can't allocate vcan devices array!\n");
241                 return -ENOMEM;
242         }
243
244         /* Clear the pointer array */
245         memset(vcan_devs, 0, numdev * sizeof(struct net_device *));
246
247         for (i = 0; i < numdev; i++) {
248                 if (!(vcan_devs[i] = alloc_netdev(STATSIZE, "vcan%d",
249                                                   vcan_init))) {
250                         printk(KERN_ERR "vcan: error allocating net_device\n");
251                         result = -ENOMEM;
252                         goto out;
253                 } else if ((result = register_netdev(vcan_devs[i])) < 0) {
254                         printk(KERN_ERR "vcan: error %d registering "
255                                "interface %s\n",
256                                result, vcan_devs[i]->name);
257                         free_netdev(vcan_devs[i]);
258                         vcan_devs[i] = NULL;
259                         goto out;
260                 } else {
261                         DBG("successfully registered interface %s\n",
262                             vcan_devs[i]->name);
263                         ndev++;
264                 }
265         }
266
267         if (ndev)
268                 return 0;
269
270  out:
271         for (i = 0; i < numdev; i++) {
272                 if (vcan_devs[i]) {
273                         unregister_netdev(vcan_devs[i]);
274                         free_netdev(vcan_devs[i]);
275                 }
276         }
277
278         kfree(vcan_devs);
279
280         return result;
281 }
282
283 static __exit void vcan_cleanup_module(void)
284 {
285         int i;
286
287         if (!vcan_devs)
288                 return;
289
290         for (i = 0; i < numdev; i++) {
291                 if (vcan_devs[i]) {
292                         unregister_netdev(vcan_devs[i]);
293                         free_netdev(vcan_devs[i]);
294                 }
295         }
296
297         kfree(vcan_devs);
298 }
299
300 module_init(vcan_init_module);
301 module_exit(vcan_cleanup_module);