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