root/arch/xtensa/platforms/iss/network.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. split_if_spec
  2. setup_etheraddr
  3. tuntap_open
  4. tuntap_close
  5. tuntap_read
  6. tuntap_write
  7. tuntap_protocol
  8. tuntap_poll
  9. tuntap_probe
  10. iss_net_rx
  11. iss_net_poll
  12. iss_net_timer
  13. iss_net_open
  14. iss_net_close
  15. iss_net_start_xmit
  16. iss_net_get_stats
  17. iss_net_set_multicast_list
  18. iss_net_tx_timeout
  19. iss_net_set_mac
  20. iss_net_change_mtu
  21. iss_net_user_timer_expire
  22. iss_net_configure
  23. iss_net_setup
  24. iss_net_init

   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 static DEFINE_SPINLOCK(opened_lock);
  42 static LIST_HEAD(opened);
  43 
  44 static DEFINE_SPINLOCK(devices_lock);
  45 static 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 
  54 struct 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 
  64 struct 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 
  98 static 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 
 125 static 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 
 152 random:
 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 
 160 static 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 
 190 static 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 
 196 static 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 
 202 static 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 
 207 unsigned short tuntap_protocol(struct sk_buff *skb)
 208 {
 209         return eth_type_trans(skb, skb->dev);
 210 }
 211 
 212 static 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 
 221 static 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);
 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 
 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.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 
 313 static 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 
 349 static 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 
 360 static 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 
 390 out:
 391         spin_unlock_bh(&lp->lock);
 392         return err;
 393 }
 394 
 395 static 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 
 413 static 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 
 448 static 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 
 454 static void iss_net_set_multicast_list(struct net_device *dev)
 455 {
 456 }
 457 
 458 static void iss_net_tx_timeout(struct net_device *dev)
 459 {
 460 }
 461 
 462 static 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 
 475 static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
 476 {
 477         return -EINVAL;
 478 }
 479 
 480 void iss_net_user_timer_expire(struct timer_list *unused)
 481 {
 482 }
 483 
 484 
 485 static struct platform_driver iss_net_driver = {
 486         .driver = {
 487                 .name  = DRIVER_NAME,
 488         },
 489 };
 490 
 491 static int driver_registered;
 492 
 493 static 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 
 505 static int iss_net_configure(int index, char *init)
 506 {
 507         struct net_device *dev;
 508         struct iss_net_private *lp;
 509         int err;
 510 
 511         dev = alloc_etherdev(sizeof(*lp));
 512         if (dev == NULL) {
 513                 pr_err("eth_configure: failed to allocate device\n");
 514                 return 1;
 515         }
 516 
 517         /* Initialize private element. */
 518 
 519         lp = netdev_priv(dev);
 520         *lp = (struct iss_net_private) {
 521                 .device_list            = LIST_HEAD_INIT(lp->device_list),
 522                 .opened_list            = LIST_HEAD_INIT(lp->opened_list),
 523                 .dev                    = dev,
 524                 .index                  = index,
 525         };
 526 
 527         spin_lock_init(&lp->lock);
 528         /*
 529          * If this name ends up conflicting with an existing registered
 530          * netdevice, that is OK, register_netdev{,ice}() will notice this
 531          * and fail.
 532          */
 533         snprintf(dev->name, sizeof(dev->name), "eth%d", index);
 534 
 535         /*
 536          * Try all transport protocols.
 537          * Note: more protocols can be added by adding '&& !X_init(lp, eth)'.
 538          */
 539 
 540         if (!tuntap_probe(lp, index, init)) {
 541                 pr_err("%s: invalid arguments. Skipping device!\n",
 542                        dev->name);
 543                 goto errout;
 544         }
 545 
 546         pr_info("Netdevice %d (%pM)\n", index, dev->dev_addr);
 547 
 548         /* sysfs register */
 549 
 550         if (!driver_registered) {
 551                 platform_driver_register(&iss_net_driver);
 552                 driver_registered = 1;
 553         }
 554 
 555         spin_lock(&devices_lock);
 556         list_add(&lp->device_list, &devices);
 557         spin_unlock(&devices_lock);
 558 
 559         lp->pdev.id = index;
 560         lp->pdev.name = DRIVER_NAME;
 561         platform_device_register(&lp->pdev);
 562         SET_NETDEV_DEV(dev, &lp->pdev.dev);
 563 
 564         dev->netdev_ops = &iss_netdev_ops;
 565         dev->mtu = lp->mtu;
 566         dev->watchdog_timeo = (HZ >> 1);
 567         dev->irq = -1;
 568 
 569         rtnl_lock();
 570         err = register_netdevice(dev);
 571         rtnl_unlock();
 572 
 573         if (err) {
 574                 pr_err("%s: error registering net device!\n", dev->name);
 575                 /* XXX: should we call ->remove() here? */
 576                 free_netdev(dev);
 577                 return 1;
 578         }
 579 
 580         timer_setup(&lp->tl, iss_net_user_timer_expire, 0);
 581 
 582         return 0;
 583 
 584 errout:
 585         /* FIXME: unregister; free, etc.. */
 586         return -EIO;
 587 }
 588 
 589 /* ------------------------------------------------------------------------- */
 590 
 591 /* Filled in during early boot */
 592 
 593 struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
 594 
 595 struct iss_net_init {
 596         struct list_head list;
 597         char *init;             /* init string */
 598         int index;
 599 };
 600 
 601 /*
 602  * Parse the command line and look for 'ethX=...' fields, and register all
 603  * those fields. They will be later initialized in iss_net_init.
 604  */
 605 
 606 static int __init iss_net_setup(char *str)
 607 {
 608         struct iss_net_private *device = NULL;
 609         struct iss_net_init *new;
 610         struct list_head *ele;
 611         char *end;
 612         int rc;
 613         unsigned n;
 614 
 615         end = strchr(str, '=');
 616         if (!end) {
 617                 pr_err("Expected '=' after device number\n");
 618                 return 1;
 619         }
 620         *end = 0;
 621         rc = kstrtouint(str, 0, &n);
 622         *end = '=';
 623         if (rc < 0) {
 624                 pr_err("Failed to parse '%s'\n", str);
 625                 return 1;
 626         }
 627         str = end;
 628 
 629         spin_lock(&devices_lock);
 630 
 631         list_for_each(ele, &devices) {
 632                 device = list_entry(ele, struct iss_net_private, device_list);
 633                 if (device->index == n)
 634                         break;
 635         }
 636 
 637         spin_unlock(&devices_lock);
 638 
 639         if (device && device->index == n) {
 640                 pr_err("Device %u already configured\n", n);
 641                 return 1;
 642         }
 643 
 644         new = memblock_alloc(sizeof(*new), SMP_CACHE_BYTES);
 645         if (new == NULL) {
 646                 pr_err("Alloc_bootmem failed\n");
 647                 return 1;
 648         }
 649 
 650         INIT_LIST_HEAD(&new->list);
 651         new->index = n;
 652         new->init = str + 1;
 653 
 654         list_add_tail(&new->list, &eth_cmd_line);
 655         return 1;
 656 }
 657 
 658 __setup("eth", iss_net_setup);
 659 
 660 /*
 661  * Initialize all ISS Ethernet devices previously registered in iss_net_setup.
 662  */
 663 
 664 static int iss_net_init(void)
 665 {
 666         struct list_head *ele, *next;
 667 
 668         /* Walk through all Ethernet devices specified in the command line. */
 669 
 670         list_for_each_safe(ele, next, &eth_cmd_line) {
 671                 struct iss_net_init *eth;
 672                 eth = list_entry(ele, struct iss_net_init, list);
 673                 iss_net_configure(eth->index, eth->init);
 674         }
 675 
 676         return 1;
 677 }
 678 device_initcall(iss_net_init);

/* [<][>][^][v][top][bottom][index][help] */