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