• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * arch/xtensa/platforms/iss/network.c
4  *
5  * Platform specific initialization.
6  *
7  * Authors: Chris Zankel <chris@zankel.net>
8  * Based on work form the UML team.
9  *
10  * Copyright 2005 Tensilica Inc.
11  *
12  * This program is free software; you can redistribute  it and/or modify it
13  * under  the terms of  the GNU General  Public License as published by the
14  * Free Software Foundation;  either version 2 of the  License, or (at your
15  * option) any later version.
16  *
17  */
18 
19 #include <linux/list.h>
20 #include <linux/irq.h>
21 #include <linux/spinlock.h>
22 #include <linux/slab.h>
23 #include <linux/timer.h>
24 #include <linux/if_ether.h>
25 #include <linux/inetdevice.h>
26 #include <linux/init.h>
27 #include <linux/if_tun.h>
28 #include <linux/etherdevice.h>
29 #include <linux/interrupt.h>
30 #include <linux/ioctl.h>
31 #include <linux/bootmem.h>
32 #include <linux/ethtool.h>
33 #include <linux/rtnetlink.h>
34 #include <linux/platform_device.h>
35 
36 #include <platform/simcall.h>
37 
38 #define DRIVER_NAME "iss-netdev"
39 #define ETH_MAX_PACKET 1500
40 #define ETH_HEADER_OTHER 14
41 #define ISS_NET_TIMER_VALUE (HZ / 10)
42 
43 
44 static DEFINE_SPINLOCK(opened_lock);
45 static LIST_HEAD(opened);
46 
47 static DEFINE_SPINLOCK(devices_lock);
48 static LIST_HEAD(devices);
49 
50 /* ------------------------------------------------------------------------- */
51 
52 /* We currently only support the TUNTAP transport protocol. */
53 
54 #define TRANSPORT_TUNTAP_NAME "tuntap"
55 #define TRANSPORT_TUNTAP_MTU ETH_MAX_PACKET
56 
57 struct tuntap_info {
58 	char dev_name[IFNAMSIZ];
59 	int fd;
60 };
61 
62 /* ------------------------------------------------------------------------- */
63 
64 
65 /* This structure contains out private information for the driver. */
66 
67 struct iss_net_private {
68 	struct list_head device_list;
69 	struct list_head opened_list;
70 
71 	spinlock_t lock;
72 	struct net_device *dev;
73 	struct platform_device pdev;
74 	struct timer_list tl;
75 	struct net_device_stats stats;
76 
77 	struct timer_list timer;
78 	unsigned int timer_val;
79 
80 	int index;
81 	int mtu;
82 
83 	struct {
84 		union {
85 			struct tuntap_info tuntap;
86 		} info;
87 
88 		int (*open)(struct iss_net_private *lp);
89 		void (*close)(struct iss_net_private *lp);
90 		int (*read)(struct iss_net_private *lp, struct sk_buff **skb);
91 		int (*write)(struct iss_net_private *lp, struct sk_buff **skb);
92 		unsigned short (*protocol)(struct sk_buff *skb);
93 		int (*poll)(struct iss_net_private *lp);
94 	} tp;
95 
96 };
97 
98 /* ================================ HELPERS ================================ */
99 
100 
split_if_spec(char * str,...)101 static char *split_if_spec(char *str, ...)
102 {
103 	char **arg, *end;
104 	va_list ap;
105 
106 	va_start(ap, str);
107 	while ((arg = va_arg(ap, char**)) != NULL) {
108 		if (*str == '\0') {
109 			va_end(ap);
110 			return NULL;
111 		}
112 		end = strchr(str, ',');
113 		if (end != str)
114 			*arg = str;
115 		if (end == NULL) {
116 			va_end(ap);
117 			return NULL;
118 		}
119 		*end++ = '\0';
120 		str = end;
121 	}
122 	va_end(ap);
123 	return str;
124 }
125 
126 /* Set Ethernet address of the specified device. */
127 
setup_etheraddr(struct net_device * dev,char * str)128 static void setup_etheraddr(struct net_device *dev, char *str)
129 {
130 	unsigned char *addr = dev->dev_addr;
131 
132 	if (str == NULL)
133 		goto random;
134 
135 	if (!mac_pton(str, addr)) {
136 		pr_err("%s: failed to parse '%s' as an ethernet address\n",
137 		       dev->name, str);
138 		goto random;
139 	}
140 	if (is_multicast_ether_addr(addr)) {
141 		pr_err("%s: attempt to assign a multicast ethernet address\n",
142 		       dev->name);
143 		goto random;
144 	}
145 	if (!is_valid_ether_addr(addr)) {
146 		pr_err("%s: attempt to assign an invalid ethernet address\n",
147 		       dev->name);
148 		goto random;
149 	}
150 	if (!is_local_ether_addr(addr))
151 		pr_warn("%s: assigning a globally valid ethernet address\n",
152 			dev->name);
153 	return;
154 
155 random:
156 	pr_info("%s: choosing a random ethernet address\n",
157 		dev->name);
158 	eth_hw_addr_random(dev);
159 }
160 
161 /* ======================= TUNTAP TRANSPORT INTERFACE ====================== */
162 
tuntap_open(struct iss_net_private * lp)163 static int tuntap_open(struct iss_net_private *lp)
164 {
165 	struct ifreq ifr;
166 	char *dev_name = lp->tp.info.tuntap.dev_name;
167 	int err = -EINVAL;
168 	int fd;
169 
170 	fd = simc_open("/dev/net/tun", 02, 0); /* O_RDWR */
171 	if (fd < 0) {
172 		pr_err("%s: failed to open /dev/net/tun, returned %d (errno = %d)\n",
173 		       lp->dev->name, fd, errno);
174 		return fd;
175 	}
176 
177 	memset(&ifr, 0, sizeof(ifr));
178 	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
179 	strlcpy(ifr.ifr_name, dev_name, sizeof(ifr.ifr_name));
180 
181 	err = simc_ioctl(fd, TUNSETIFF, &ifr);
182 	if (err < 0) {
183 		pr_err("%s: failed to set interface %s, returned %d (errno = %d)\n",
184 		       lp->dev->name, dev_name, err, errno);
185 		simc_close(fd);
186 		return err;
187 	}
188 
189 	lp->tp.info.tuntap.fd = fd;
190 	return err;
191 }
192 
tuntap_close(struct iss_net_private * lp)193 static void tuntap_close(struct iss_net_private *lp)
194 {
195 	simc_close(lp->tp.info.tuntap.fd);
196 	lp->tp.info.tuntap.fd = -1;
197 }
198 
tuntap_read(struct iss_net_private * lp,struct sk_buff ** skb)199 static int tuntap_read(struct iss_net_private *lp, struct sk_buff **skb)
200 {
201 	return simc_read(lp->tp.info.tuntap.fd,
202 			(*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER);
203 }
204 
tuntap_write(struct iss_net_private * lp,struct sk_buff ** skb)205 static int tuntap_write(struct iss_net_private *lp, struct sk_buff **skb)
206 {
207 	return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
208 }
209 
tuntap_protocol(struct sk_buff * skb)210 unsigned short tuntap_protocol(struct sk_buff *skb)
211 {
212 	return eth_type_trans(skb, skb->dev);
213 }
214 
tuntap_poll(struct iss_net_private * lp)215 static int tuntap_poll(struct iss_net_private *lp)
216 {
217 	return simc_poll(lp->tp.info.tuntap.fd);
218 }
219 
220 /*
221  * ethX=tuntap,[mac address],device name
222  */
223 
tuntap_probe(struct iss_net_private * lp,int index,char * init)224 static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
225 {
226 	struct net_device *dev = lp->dev;
227 	char *dev_name = NULL, *mac_str = NULL, *rem = NULL;
228 
229 	/* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */
230 
231 	if (strncmp(init, TRANSPORT_TUNTAP_NAME,
232 		    sizeof(TRANSPORT_TUNTAP_NAME) - 1))
233 		return 0;
234 
235 	init += sizeof(TRANSPORT_TUNTAP_NAME) - 1;
236 	if (*init == ',') {
237 		rem = split_if_spec(init + 1, &mac_str, &dev_name);
238 		if (rem != NULL) {
239 			pr_err("%s: extra garbage on specification : '%s'\n",
240 			       dev->name, rem);
241 			return 0;
242 		}
243 	} else if (*init != '\0') {
244 		pr_err("%s: invalid argument: %s. Skipping device!\n",
245 		       dev->name, init);
246 		return 0;
247 	}
248 
249 	if (!dev_name) {
250 		pr_err("%s: missing tuntap device name\n", dev->name);
251 		return 0;
252 	}
253 
254 	strlcpy(lp->tp.info.tuntap.dev_name, dev_name,
255 		sizeof(lp->tp.info.tuntap.dev_name));
256 
257 	setup_etheraddr(dev, mac_str);
258 
259 	lp->mtu = TRANSPORT_TUNTAP_MTU;
260 
261 	lp->tp.info.tuntap.fd = -1;
262 
263 	lp->tp.open = tuntap_open;
264 	lp->tp.close = tuntap_close;
265 	lp->tp.read = tuntap_read;
266 	lp->tp.write = tuntap_write;
267 	lp->tp.protocol = tuntap_protocol;
268 	lp->tp.poll = tuntap_poll;
269 
270 	return 1;
271 }
272 
273 /* ================================ ISS NET ================================ */
274 
iss_net_rx(struct net_device * dev)275 static int iss_net_rx(struct net_device *dev)
276 {
277 	struct iss_net_private *lp = netdev_priv(dev);
278 	int pkt_len;
279 	struct sk_buff *skb;
280 
281 	/* Check if there is any new data. */
282 
283 	if (lp->tp.poll(lp) == 0)
284 		return 0;
285 
286 	/* Try to allocate memory, if it fails, try again next round. */
287 
288 	skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER);
289 	if (skb == NULL) {
290 		lp->stats.rx_dropped++;
291 		return 0;
292 	}
293 
294 	skb_reserve(skb, 2);
295 
296 	/* Setup skb */
297 
298 	skb->dev = dev;
299 	skb_reset_mac_header(skb);
300 	pkt_len = lp->tp.read(lp, &skb);
301 	skb_put(skb, pkt_len);
302 
303 	if (pkt_len > 0) {
304 		skb_trim(skb, pkt_len);
305 		skb->protocol = lp->tp.protocol(skb);
306 
307 		lp->stats.rx_bytes += skb->len;
308 		lp->stats.rx_packets++;
309 		netif_rx_ni(skb);
310 		return pkt_len;
311 	}
312 	kfree_skb(skb);
313 	return pkt_len;
314 }
315 
iss_net_poll(void)316 static int iss_net_poll(void)
317 {
318 	struct list_head *ele;
319 	int err, ret = 0;
320 
321 	spin_lock(&opened_lock);
322 
323 	list_for_each(ele, &opened) {
324 		struct iss_net_private *lp;
325 
326 		lp = list_entry(ele, struct iss_net_private, opened_list);
327 
328 		if (!netif_running(lp->dev))
329 			break;
330 
331 		spin_lock(&lp->lock);
332 
333 		while ((err = iss_net_rx(lp->dev)) > 0)
334 			ret++;
335 
336 		spin_unlock(&lp->lock);
337 
338 		if (err < 0) {
339 			pr_err("Device '%s' read returned %d, shutting it down\n",
340 			       lp->dev->name, err);
341 			dev_close(lp->dev);
342 		} else {
343 			/* FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ); */
344 		}
345 	}
346 
347 	spin_unlock(&opened_lock);
348 	return ret;
349 }
350 
351 
iss_net_timer(unsigned long priv)352 static void iss_net_timer(unsigned long priv)
353 {
354 	struct iss_net_private *lp = (struct iss_net_private *)priv;
355 
356 	iss_net_poll();
357 	spin_lock(&lp->lock);
358 	mod_timer(&lp->timer, jiffies + lp->timer_val);
359 	spin_unlock(&lp->lock);
360 }
361 
362 
iss_net_open(struct net_device * dev)363 static int iss_net_open(struct net_device *dev)
364 {
365 	struct iss_net_private *lp = netdev_priv(dev);
366 	int err;
367 
368 	spin_lock_bh(&lp->lock);
369 
370 	err = lp->tp.open(lp);
371 	if (err < 0)
372 		goto out;
373 
374 	netif_start_queue(dev);
375 
376 	/* clear buffer - it can happen that the host side of the interface
377 	 * is full when we get here. In this case, new data is never queued,
378 	 * SIGIOs never arrive, and the net never works.
379 	 */
380 	while ((err = iss_net_rx(dev)) > 0)
381 		;
382 
383 	spin_unlock_bh(&lp->lock);
384 	spin_lock_bh(&opened_lock);
385 	list_add(&lp->opened_list, &opened);
386 	spin_unlock_bh(&opened_lock);
387 	spin_lock_bh(&lp->lock);
388 
389 	init_timer(&lp->timer);
390 	lp->timer_val = ISS_NET_TIMER_VALUE;
391 	lp->timer.data = (unsigned long) lp;
392 	lp->timer.function = iss_net_timer;
393 	mod_timer(&lp->timer, jiffies + lp->timer_val);
394 
395 out:
396 	spin_unlock_bh(&lp->lock);
397 	return err;
398 }
399 
iss_net_close(struct net_device * dev)400 static int iss_net_close(struct net_device *dev)
401 {
402 	struct iss_net_private *lp = netdev_priv(dev);
403 	netif_stop_queue(dev);
404 	spin_lock_bh(&lp->lock);
405 
406 	spin_lock(&opened_lock);
407 	list_del(&opened);
408 	spin_unlock(&opened_lock);
409 
410 	del_timer_sync(&lp->timer);
411 
412 	lp->tp.close(lp);
413 
414 	spin_unlock_bh(&lp->lock);
415 	return 0;
416 }
417 
iss_net_start_xmit(struct sk_buff * skb,struct net_device * dev)418 static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
419 {
420 	struct iss_net_private *lp = netdev_priv(dev);
421 	int len;
422 
423 	netif_stop_queue(dev);
424 	spin_lock_bh(&lp->lock);
425 
426 	len = lp->tp.write(lp, &skb);
427 
428 	if (len == skb->len) {
429 		lp->stats.tx_packets++;
430 		lp->stats.tx_bytes += skb->len;
431 		dev->trans_start = jiffies;
432 		netif_start_queue(dev);
433 
434 		/* this is normally done in the interrupt when tx finishes */
435 		netif_wake_queue(dev);
436 
437 	} else if (len == 0) {
438 		netif_start_queue(dev);
439 		lp->stats.tx_dropped++;
440 
441 	} else {
442 		netif_start_queue(dev);
443 		pr_err("%s: %s failed(%d)\n", dev->name, __func__, len);
444 	}
445 
446 	spin_unlock_bh(&lp->lock);
447 
448 	dev_kfree_skb(skb);
449 	return NETDEV_TX_OK;
450 }
451 
452 
iss_net_get_stats(struct net_device * dev)453 static struct net_device_stats *iss_net_get_stats(struct net_device *dev)
454 {
455 	struct iss_net_private *lp = netdev_priv(dev);
456 	return &lp->stats;
457 }
458 
iss_net_set_multicast_list(struct net_device * dev)459 static void iss_net_set_multicast_list(struct net_device *dev)
460 {
461 }
462 
iss_net_tx_timeout(struct net_device * dev)463 static void iss_net_tx_timeout(struct net_device *dev)
464 {
465 }
466 
iss_net_set_mac(struct net_device * dev,void * addr)467 static int iss_net_set_mac(struct net_device *dev, void *addr)
468 {
469 	struct iss_net_private *lp = netdev_priv(dev);
470 	struct sockaddr *hwaddr = addr;
471 
472 	if (!is_valid_ether_addr(hwaddr->sa_data))
473 		return -EADDRNOTAVAIL;
474 	spin_lock_bh(&lp->lock);
475 	memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
476 	spin_unlock_bh(&lp->lock);
477 	return 0;
478 }
479 
iss_net_change_mtu(struct net_device * dev,int new_mtu)480 static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
481 {
482 	return -EINVAL;
483 }
484 
iss_net_user_timer_expire(unsigned long _conn)485 void iss_net_user_timer_expire(unsigned long _conn)
486 {
487 }
488 
489 
490 static struct platform_driver iss_net_driver = {
491 	.driver = {
492 		.name  = DRIVER_NAME,
493 	},
494 };
495 
496 static int driver_registered;
497 
498 static const struct net_device_ops iss_netdev_ops = {
499 	.ndo_open		= iss_net_open,
500 	.ndo_stop		= iss_net_close,
501 	.ndo_get_stats		= iss_net_get_stats,
502 	.ndo_start_xmit		= iss_net_start_xmit,
503 	.ndo_validate_addr	= eth_validate_addr,
504 	.ndo_change_mtu		= iss_net_change_mtu,
505 	.ndo_set_mac_address	= iss_net_set_mac,
506 	.ndo_tx_timeout		= iss_net_tx_timeout,
507 	.ndo_set_rx_mode	= iss_net_set_multicast_list,
508 };
509 
iss_net_configure(int index,char * init)510 static int iss_net_configure(int index, char *init)
511 {
512 	struct net_device *dev;
513 	struct iss_net_private *lp;
514 	int err;
515 
516 	dev = alloc_etherdev(sizeof(*lp));
517 	if (dev == NULL) {
518 		pr_err("eth_configure: failed to allocate device\n");
519 		return 1;
520 	}
521 
522 	/* Initialize private element. */
523 
524 	lp = netdev_priv(dev);
525 	*lp = (struct iss_net_private) {
526 		.device_list		= LIST_HEAD_INIT(lp->device_list),
527 		.opened_list		= LIST_HEAD_INIT(lp->opened_list),
528 		.dev			= dev,
529 		.index			= index,
530 	};
531 
532 	spin_lock_init(&lp->lock);
533 	/*
534 	 * If this name ends up conflicting with an existing registered
535 	 * netdevice, that is OK, register_netdev{,ice}() will notice this
536 	 * and fail.
537 	 */
538 	snprintf(dev->name, sizeof(dev->name), "eth%d", index);
539 
540 	/*
541 	 * Try all transport protocols.
542 	 * Note: more protocols can be added by adding '&& !X_init(lp, eth)'.
543 	 */
544 
545 	if (!tuntap_probe(lp, index, init)) {
546 		pr_err("%s: invalid arguments. Skipping device!\n",
547 		       dev->name);
548 		goto errout;
549 	}
550 
551 	pr_info("Netdevice %d (%pM)\n", index, dev->dev_addr);
552 
553 	/* sysfs register */
554 
555 	if (!driver_registered) {
556 		platform_driver_register(&iss_net_driver);
557 		driver_registered = 1;
558 	}
559 
560 	spin_lock(&devices_lock);
561 	list_add(&lp->device_list, &devices);
562 	spin_unlock(&devices_lock);
563 
564 	lp->pdev.id = index;
565 	lp->pdev.name = DRIVER_NAME;
566 	platform_device_register(&lp->pdev);
567 	SET_NETDEV_DEV(dev, &lp->pdev.dev);
568 
569 	dev->netdev_ops = &iss_netdev_ops;
570 	dev->mtu = lp->mtu;
571 	dev->watchdog_timeo = (HZ >> 1);
572 	dev->irq = -1;
573 
574 	rtnl_lock();
575 	err = register_netdevice(dev);
576 	rtnl_unlock();
577 
578 	if (err) {
579 		pr_err("%s: error registering net device!\n", dev->name);
580 		/* XXX: should we call ->remove() here? */
581 		free_netdev(dev);
582 		return 1;
583 	}
584 
585 	init_timer(&lp->tl);
586 	lp->tl.function = iss_net_user_timer_expire;
587 
588 	return 0;
589 
590 errout:
591 	/* FIXME: unregister; free, etc.. */
592 	return -EIO;
593 }
594 
595 /* ------------------------------------------------------------------------- */
596 
597 /* Filled in during early boot */
598 
599 struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
600 
601 struct iss_net_init {
602 	struct list_head list;
603 	char *init;		/* init string */
604 	int index;
605 };
606 
607 /*
608  * Parse the command line and look for 'ethX=...' fields, and register all
609  * those fields. They will be later initialized in iss_net_init.
610  */
611 
612 #define ERR KERN_ERR "iss_net_setup: "
613 
iss_net_setup(char * str)614 static int __init iss_net_setup(char *str)
615 {
616 	struct iss_net_private *device = NULL;
617 	struct iss_net_init *new;
618 	struct list_head *ele;
619 	char *end;
620 	int rc;
621 	unsigned n;
622 
623 	end = strchr(str, '=');
624 	if (!end) {
625 		printk(ERR "Expected '=' after device number\n");
626 		return 1;
627 	}
628 	*end = 0;
629 	rc = kstrtouint(str, 0, &n);
630 	*end = '=';
631 	if (rc < 0) {
632 		printk(ERR "Failed to parse '%s'\n", str);
633 		return 1;
634 	}
635 	str = end;
636 
637 	spin_lock(&devices_lock);
638 
639 	list_for_each(ele, &devices) {
640 		device = list_entry(ele, struct iss_net_private, device_list);
641 		if (device->index == n)
642 			break;
643 	}
644 
645 	spin_unlock(&devices_lock);
646 
647 	if (device && device->index == n) {
648 		printk(ERR "Device %u already configured\n", n);
649 		return 1;
650 	}
651 
652 	new = alloc_bootmem(sizeof(*new));
653 	if (new == NULL) {
654 		printk(ERR "Alloc_bootmem failed\n");
655 		return 1;
656 	}
657 
658 	INIT_LIST_HEAD(&new->list);
659 	new->index = n;
660 	new->init = str + 1;
661 
662 	list_add_tail(&new->list, &eth_cmd_line);
663 	return 1;
664 }
665 
666 #undef ERR
667 
668 __setup("eth", iss_net_setup);
669 
670 /*
671  * Initialize all ISS Ethernet devices previously registered in iss_net_setup.
672  */
673 
iss_net_init(void)674 static int iss_net_init(void)
675 {
676 	struct list_head *ele, *next;
677 
678 	/* Walk through all Ethernet devices specified in the command line. */
679 
680 	list_for_each_safe(ele, next, &eth_cmd_line) {
681 		struct iss_net_init *eth;
682 		eth = list_entry(ele, struct iss_net_init, list);
683 		iss_net_configure(eth->index, eth->init);
684 	}
685 
686 	return 1;
687 }
688 device_initcall(iss_net_init);
689