[lantiq] move files/ -> files-3.3/
[openwrt/svn-archive/archive.git] / target / linux / lantiq / files-3.3 / drivers / net / ethernet / svip_virtual_eth.c
1 /******************************************************************************
2
3 Copyright (c) 2007
4 Infineon Technologies AG
5 Am Campeon 1-12; 81726 Munich, Germany
6
7 THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
8 WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
9 SOFTWARE IS FREE OF CHARGE.
10
11 THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
12 ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
13 WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
14 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
15 OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
16 PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
17 PROPERTY INFRINGEMENT.
18
19 EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
20 FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
21 OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 DEALINGS IN THE SOFTWARE.
24
25 ****************************************************************************
26 Module : svip_virtual_eth.c
27
28 Description : This file contains network driver implementation for a
29 Virtual Ethernet interface. The Virtual Ethernet interface
30 is part of Infineon's VINETIC-SVIP Linux BSP.
31 *******************************************************************************/
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/netdevice.h>
35 #include <linux/platform_device.h>
36 #include <linux/etherdevice.h>
37 #include <linux/init.h>
38
39 #define SVIP_VETH_VER_STR "3.0"
40 #define SVIP_VETH_INFO_STR \
41 "@(#)SVIP virtual ethernet interface, version " SVIP_VETH_VER_STR
42
43 /******************************************************************************
44 * Local define/macro definitions
45 ******************************************************************************/
46 struct svip_ve_priv
47 {
48 struct net_device_stats stats;
49 };
50
51 /******************************************************************************
52 * Global function declarations
53 ******************************************************************************/
54 int svip_ve_rx(struct sk_buff *skb);
55
56 /******************************************************************************
57 * Local variable declarations
58 ******************************************************************************/
59 static struct net_device *svip_ve_dev;
60 static int watchdog_timeout = 10*HZ;
61 static int (*svip_ve_mps_xmit)(struct sk_buff *skb) = NULL;
62
63
64 /******************************************************************************
65 * Global function declarations
66 ******************************************************************************/
67
68 /**
69 * Called by MPS driver to register a transmit routine called for each outgoing
70 * VoFW0 message.
71 *
72 * \param mps_xmit pointer to transmit routine
73 *
74 * \return none
75 *
76 * \ingroup Internal
77 */
78 void register_mps_xmit_routine(int (*mps_xmit)(struct sk_buff *skb))
79 {
80 svip_ve_mps_xmit = mps_xmit;
81 }
82 EXPORT_SYMBOL(register_mps_xmit_routine);
83
84 /**
85 * Returns a pointer to the routine used to deliver an incoming packet/message
86 * from the MPS mailbox to the networking layer. This routine is called by MPS
87 * driver during initialisation time.
88 *
89 * \param skb pointer to incoming socket buffer
90 *
91 * \return svip_ve_rx pointer to incoming messages delivering routine
92 *
93 * \ingroup Internal
94 */
95 int (*register_mps_recv_routine(void)) (struct sk_buff *skb)
96 {
97 return svip_ve_rx;
98 }
99
100 /**
101 * Used to deliver outgoing packets to VoFW0 module through the MPS driver.
102 * Upon loading/initialisation the MPS driver is registering a transmitting
103 * routine, which is called here to deliver the packet to the VoFW0 module.
104 *
105 * \param skb pointer to skb containing outgoing data
106 * \param dev pointer to this networking device's data
107 *
108 * \return 0 on success
109 * \return non-zero on error
110 *
111 * \ingroup Internal
112 */
113 static int svip_ve_xmit(struct sk_buff *skb, struct net_device *dev)
114 {
115 int err;
116 struct svip_ve_priv *priv = netdev_priv(dev);
117 struct net_device_stats *stats = &priv->stats;
118
119 stats->tx_packets++;
120 stats->tx_bytes += skb->len;
121
122 if (svip_ve_mps_xmit)
123 {
124 err = svip_ve_mps_xmit(skb);
125 if (err)
126 stats->tx_errors++;
127 dev->trans_start = jiffies;
128 return err;
129 }
130 else
131 printk(KERN_ERR "%s: MPS driver not registered, outgoing packet not delivered\n", dev->name);
132
133 dev_kfree_skb(skb);
134
135 return -1;
136 }
137
138 /**
139 * Called by MPS driver upon receipt of a new message from VoFW0 module in
140 * the data inbox. The packet is pushed up the IP module for further processing.
141 *
142 * \param skb pointer to skb containing the incoming message
143 *
144 * \return 0 on success
145 * \return non-zero on error
146 *
147 * \ingroup Internal
148 */
149 int svip_ve_rx(struct sk_buff *skb)
150 {
151 int err;
152 struct svip_ve_priv *priv = netdev_priv(svip_ve_dev);
153 struct net_device_stats *stats = &priv->stats;
154
155 skb->dev = svip_ve_dev;
156 skb->protocol = eth_type_trans(skb, svip_ve_dev);
157
158 stats->rx_packets++;
159 stats->rx_bytes += skb->len;
160
161 err = netif_rx(skb);
162 switch (err)
163 {
164 case NET_RX_SUCCESS:
165 return 0;
166 break;
167 case NET_RX_DROP:
168 default:
169 stats->rx_dropped++;
170 break;
171 }
172
173 return 1;
174 }
175 EXPORT_SYMBOL(svip_ve_rx);
176
177 /**
178 * Returns a pointer to the device's networking statistics data
179 *
180 * \param dev pointer to this networking device's data
181 *
182 * \return stats pointer to this network device's statistics data
183 *
184 * \ingroup Internal
185 */
186 static struct net_device_stats *svip_ve_get_stats(struct net_device *dev)
187 {
188 struct svip_ve_priv *priv = netdev_priv(dev);
189
190 return &priv->stats;
191 }
192
193 static void svip_ve_tx_timeout(struct net_device *dev)
194 {
195 struct svip_ve_priv *priv = netdev_priv(dev);
196
197 priv->stats.tx_errors++;
198 netif_wake_queue(dev);
199 }
200
201 /**
202 * Device open routine. Called e.g. upon setting of an IP address using,
203 * 'ifconfig veth0 YYY.YYY.YYY.YYY netmask ZZZ.ZZZ.ZZZ.ZZZ' or
204 * 'ifconfig veth0 up'
205 *
206 * \param dev pointer to this network device's data
207 *
208 * \return 0 on success
209 * \return non-zero on error
210 *
211 * \ingroup Internal
212 */
213 int svip_ve_open(struct net_device *dev)
214 {
215 netif_start_queue(dev);
216 return 0;
217 }
218
219 /**
220 * Device close routine. Called e.g. upon calling
221 * 'ifconfig veth0 down'
222 *
223 * \param dev pointer to this network device's data
224 *
225 * \return 0 on success
226 * \return non-zero on error
227 *
228 * \ingroup Internal
229 */
230
231 int svip_ve_release(struct net_device *dev)
232 {
233 netif_stop_queue(dev);
234 return 0;
235 }
236
237 static int svip_ve_dev_init(struct net_device *dev);
238
239 static const struct net_device_ops svip_virtual_eth_netdev_ops = {
240 .ndo_init = svip_ve_dev_init,
241 .ndo_open = svip_ve_open,
242 .ndo_stop = svip_ve_release,
243 .ndo_start_xmit = svip_ve_xmit,
244 .ndo_get_stats = svip_ve_get_stats,
245 .ndo_tx_timeout = svip_ve_tx_timeout,
246 };
247
248
249 /**
250 * Device initialisation routine which registers device interface routines.
251 * It is called upon execution of 'register_netdev' routine.
252 *
253 * \param dev pointer to this network device's data
254 *
255 * \return 0 on success
256 * \return non-zero on error
257 *
258 * \ingroup Internal
259 */
260 static int svip_ve_dev_init(struct net_device *dev)
261 {
262 ether_setup(dev); /* assign some of the fields */
263
264 dev->watchdog_timeo = watchdog_timeout;
265 memset(netdev_priv(dev), 0, sizeof(struct svip_ve_priv));
266 dev->flags |= IFF_NOARP|IFF_PROMISC;
267 dev->flags &= ~IFF_MULTICAST;
268
269 /* dedicated MAC address to veth0, 00:03:19:00:15:80 */
270 dev->dev_addr[0] = 0x00;
271 dev->dev_addr[1] = 0x03;
272 dev->dev_addr[2] = 0x19;
273 dev->dev_addr[3] = 0x00;
274 dev->dev_addr[4] = 0x15;
275 dev->dev_addr[5] = 0x80;
276
277 return 0;
278 }
279
280 static int svip_ve_probe(struct platform_device *dev)
281 {
282 int result = 0;
283
284 svip_ve_dev = alloc_etherdev(sizeof(struct svip_ve_priv));
285 svip_ve_dev->netdev_ops = &svip_virtual_eth_netdev_ops;
286
287 strcpy(svip_ve_dev->name, "veth%d");
288
289 result = register_netdev(svip_ve_dev);
290 if (result)
291 {
292 printk(KERN_INFO "error %i registering device \"%s\"\n", result, svip_ve_dev->name);
293 goto out;
294 }
295
296 printk (KERN_INFO "%s, (c) 2009, Lantiq Deutschland GmbH\n", &SVIP_VETH_INFO_STR[4]);
297
298 out:
299 return result;
300 }
301
302 static int svip_ve_remove(struct platform_device *dev)
303 {
304 unregister_netdev(svip_ve_dev);
305 free_netdev(svip_ve_dev);
306
307 printk(KERN_INFO "%s removed\n", svip_ve_dev->name);
308 return 0;
309 }
310
311 static struct platform_driver svip_ve_driver = {
312 .probe = svip_ve_probe,
313 .remove = svip_ve_remove,
314 .driver = {
315 .name = "ifxmips_svip_ve",
316 .owner = THIS_MODULE,
317 },
318 };
319
320 /**
321 * Module/driver entry routine
322 */
323 static int __init svip_ve_init_module(void)
324 {
325 int ret;
326
327 ret = platform_driver_register(&svip_ve_driver);
328 if (ret)
329 printk(KERN_INFO "SVIP: error(%d) registering virtual Ethernet driver!\n", ret);
330 return ret;
331 }
332
333 /**
334 * Module exit routine (never called for statically linked driver)
335 */
336 static void __exit svip_ve_cleanup_module(void)
337 {
338 platform_driver_unregister(&svip_ve_driver);
339 }
340
341 module_init(svip_ve_init_module);
342 module_exit(svip_ve_cleanup_module);
343 MODULE_LICENSE("GPL");
344 MODULE_DESCRIPTION("virtual ethernet driver for LANTIQ SVIP system");
345
346 EXPORT_SYMBOL(register_mps_recv_routine);