uboot/net/eth-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2001-2015
   4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   5 * Joe Hershberger, National Instruments
   6 */
   7
   8#define LOG_CATEGORY UCLASS_ETH
   9
  10#include <common.h>
  11#include <bootstage.h>
  12#include <dm.h>
  13#include <env.h>
  14#include <log.h>
  15#include <net.h>
  16#include <asm/global_data.h>
  17#include <dm/device-internal.h>
  18#include <dm/uclass-internal.h>
  19#include <net/pcap.h>
  20#include "eth_internal.h"
  21#include <eth_phy.h>
  22
  23DECLARE_GLOBAL_DATA_PTR;
  24
  25/**
  26 * struct eth_device_priv - private structure for each Ethernet device
  27 *
  28 * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
  29 */
  30struct eth_device_priv {
  31        enum eth_state_t state;
  32        bool running;
  33};
  34
  35/**
  36 * struct eth_uclass_priv - The structure attached to the uclass itself
  37 *
  38 * @current: The Ethernet device that the network functions are using
  39 */
  40struct eth_uclass_priv {
  41        struct udevice *current;
  42};
  43
  44/* eth_errno - This stores the most recent failure code from DM functions */
  45static int eth_errno;
  46
  47static struct eth_uclass_priv *eth_get_uclass_priv(void)
  48{
  49        struct uclass *uc;
  50        int ret;
  51
  52        ret = uclass_get(UCLASS_ETH, &uc);
  53        if (ret)
  54                return NULL;
  55
  56        assert(uc);
  57        return uclass_get_priv(uc);
  58}
  59
  60void eth_set_current_to_next(void)
  61{
  62        struct eth_uclass_priv *uc_priv;
  63
  64        uc_priv = eth_get_uclass_priv();
  65        if (uc_priv->current)
  66                uclass_next_device(&uc_priv->current);
  67        if (!uc_priv->current)
  68                uclass_first_device(UCLASS_ETH, &uc_priv->current);
  69}
  70
  71/*
  72 * Typically this will simply return the active device.
  73 * In the case where the most recent active device was unset, this will attempt
  74 * to return the device with sequence id 0 (which can be configured by the
  75 * device tree). If this fails, fall back to just getting the first device.
  76 * The latter is non-deterministic and depends on the order of the probing.
  77 * If that device doesn't exist or fails to probe, this function will return
  78 * NULL.
  79 */
  80struct udevice *eth_get_dev(void)
  81{
  82        struct eth_uclass_priv *uc_priv;
  83
  84        uc_priv = eth_get_uclass_priv();
  85        if (!uc_priv)
  86                return NULL;
  87
  88        if (!uc_priv->current) {
  89                eth_errno = uclass_get_device_by_seq(UCLASS_ETH, 0,
  90                                                     &uc_priv->current);
  91                if (eth_errno)
  92                        eth_errno = uclass_first_device(UCLASS_ETH,
  93                                                        &uc_priv->current);
  94        }
  95        return uc_priv->current;
  96}
  97
  98/*
  99 * Typically this will just store a device pointer.
 100 * In case it was not probed, we will attempt to do so.
 101 * dev may be NULL to unset the active device.
 102 */
 103void eth_set_dev(struct udevice *dev)
 104{
 105        if (dev && !device_active(dev)) {
 106                eth_errno = device_probe(dev);
 107                if (eth_errno)
 108                        dev = NULL;
 109        }
 110
 111        eth_get_uclass_priv()->current = dev;
 112}
 113
 114/*
 115 * Find the udevice that either has the name passed in as devname or has an
 116 * alias named devname.
 117 */
 118struct udevice *eth_get_dev_by_name(const char *devname)
 119{
 120        int seq = -1;
 121        char *endp = NULL;
 122        const char *startp = NULL;
 123        struct udevice *it;
 124        struct uclass *uc;
 125        int len = strlen("eth");
 126        int ret;
 127
 128        /* Must be longer than 3 to be an alias */
 129        if (!strncmp(devname, "eth", len) && strlen(devname) > len) {
 130                startp = devname + len;
 131                seq = dectoul(startp, &endp);
 132        }
 133
 134        ret = uclass_get(UCLASS_ETH, &uc);
 135        if (ret)
 136                return NULL;
 137
 138        uclass_foreach_dev(it, uc) {
 139                /*
 140                 * We don't care about errors from probe here. Either they won't
 141                 * match an alias or it will match a literal name and we'll pick
 142                 * up the error when we try to probe again in eth_set_dev().
 143                 */
 144                if (device_probe(it))
 145                        continue;
 146                /* Check for the name or the sequence number to match */
 147                if (strcmp(it->name, devname) == 0 ||
 148                    (endp > startp && dev_seq(it) == seq))
 149                        return it;
 150        }
 151
 152        return NULL;
 153}
 154
 155unsigned char *eth_get_ethaddr(void)
 156{
 157        struct eth_pdata *pdata;
 158
 159        if (eth_get_dev()) {
 160                pdata = dev_get_plat(eth_get_dev());
 161                return pdata->enetaddr;
 162        }
 163
 164        return NULL;
 165}
 166
 167/* Set active state without calling start on the driver */
 168int eth_init_state_only(void)
 169{
 170        struct udevice *current;
 171        struct eth_device_priv *priv;
 172
 173        current = eth_get_dev();
 174        if (!current || !device_active(current))
 175                return -EINVAL;
 176
 177        priv = dev_get_uclass_priv(current);
 178        priv->state = ETH_STATE_ACTIVE;
 179
 180        return 0;
 181}
 182
 183/* Set passive state without calling stop on the driver */
 184void eth_halt_state_only(void)
 185{
 186        struct udevice *current;
 187        struct eth_device_priv *priv;
 188
 189        current = eth_get_dev();
 190        if (!current || !device_active(current))
 191                return;
 192
 193        priv = dev_get_uclass_priv(current);
 194        priv->state = ETH_STATE_PASSIVE;
 195}
 196
 197int eth_get_dev_index(void)
 198{
 199        if (eth_get_dev())
 200                return dev_seq(eth_get_dev());
 201        return -1;
 202}
 203
 204static int eth_write_hwaddr(struct udevice *dev)
 205{
 206        struct eth_pdata *pdata;
 207        int ret = 0;
 208
 209        if (!dev || !device_active(dev))
 210                return -EINVAL;
 211
 212        /* seq is valid since the device is active */
 213        if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev_seq(dev))) {
 214                pdata = dev_get_plat(dev);
 215                if (!is_valid_ethaddr(pdata->enetaddr)) {
 216                        printf("\nError: %s address %pM illegal value\n",
 217                               dev->name, pdata->enetaddr);
 218                        return -EINVAL;
 219                }
 220
 221                /*
 222                 * Drivers are allowed to decide not to implement this at
 223                 * run-time. E.g. Some devices may use it and some may not.
 224                 */
 225                ret = eth_get_ops(dev)->write_hwaddr(dev);
 226                if (ret == -ENOSYS)
 227                        ret = 0;
 228                if (ret)
 229                        printf("\nWarning: %s failed to set MAC address\n",
 230                               dev->name);
 231        }
 232
 233        return ret;
 234}
 235
 236static int on_ethaddr(const char *name, const char *value, enum env_op op,
 237        int flags)
 238{
 239        int index;
 240        int retval;
 241        struct udevice *dev;
 242
 243        /* look for an index after "eth" */
 244        index = dectoul(name + 3, NULL);
 245
 246        retval = uclass_find_device_by_seq(UCLASS_ETH, index, &dev);
 247        if (!retval) {
 248                struct eth_pdata *pdata = dev_get_plat(dev);
 249                switch (op) {
 250                case env_op_create:
 251                case env_op_overwrite:
 252                        string_to_enetaddr(value, pdata->enetaddr);
 253                        eth_write_hwaddr(dev);
 254                        break;
 255                case env_op_delete:
 256                        memset(pdata->enetaddr, 0, ARP_HLEN);
 257                }
 258        }
 259
 260        return 0;
 261}
 262U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
 263
 264int eth_init(void)
 265{
 266        char *ethact = env_get("ethact");
 267        char *ethrotate = env_get("ethrotate");
 268        struct udevice *current = NULL;
 269        struct udevice *old_current;
 270        int ret = -ENODEV;
 271
 272        /*
 273         * When 'ethrotate' variable is set to 'no' and 'ethact' variable
 274         * is already set to an ethernet device, we should stick to 'ethact'.
 275         */
 276        if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) {
 277                if (ethact) {
 278                        current = eth_get_dev_by_name(ethact);
 279                        if (!current)
 280                                return -EINVAL;
 281                }
 282        }
 283
 284        if (!current) {
 285                current = eth_get_dev();
 286                if (!current) {
 287                        log_err("No ethernet found.\n");
 288                        return -ENODEV;
 289                }
 290        }
 291
 292        old_current = current;
 293        do {
 294                if (current) {
 295                        debug("Trying %s\n", current->name);
 296
 297                        if (device_active(current)) {
 298                                ret = eth_get_ops(current)->start(current);
 299                                if (ret >= 0) {
 300                                        struct eth_device_priv *priv =
 301                                                dev_get_uclass_priv(current);
 302
 303                                        priv->state = ETH_STATE_ACTIVE;
 304                                        priv->running = true;
 305                                        return 0;
 306                                }
 307                        } else {
 308                                ret = eth_errno;
 309                        }
 310
 311                        debug("FAIL\n");
 312                } else {
 313                        debug("PROBE FAIL\n");
 314                }
 315
 316                /*
 317                 * If ethrotate is enabled, this will change "current",
 318                 * otherwise we will drop out of this while loop immediately
 319                 */
 320                eth_try_another(0);
 321                /* This will ensure the new "current" attempted to probe */
 322                current = eth_get_dev();
 323        } while (old_current != current);
 324
 325        return ret;
 326}
 327
 328void eth_halt(void)
 329{
 330        struct udevice *current;
 331        struct eth_device_priv *priv;
 332
 333        current = eth_get_dev();
 334        if (!current)
 335                return;
 336
 337        priv = dev_get_uclass_priv(current);
 338        if (!priv || !priv->running)
 339                return;
 340
 341        eth_get_ops(current)->stop(current);
 342        priv->state = ETH_STATE_PASSIVE;
 343        priv->running = false;
 344}
 345
 346int eth_is_active(struct udevice *dev)
 347{
 348        struct eth_device_priv *priv;
 349
 350        if (!dev || !device_active(dev))
 351                return 0;
 352
 353        priv = dev_get_uclass_priv(dev);
 354        return priv->state == ETH_STATE_ACTIVE;
 355}
 356
 357int eth_send(void *packet, int length)
 358{
 359        struct udevice *current;
 360        int ret;
 361
 362        current = eth_get_dev();
 363        if (!current)
 364                return -ENODEV;
 365
 366        if (!eth_is_active(current))
 367                return -EINVAL;
 368
 369        ret = eth_get_ops(current)->send(current, packet, length);
 370        if (ret < 0) {
 371                /* We cannot completely return the error at present */
 372                debug("%s: send() returned error %d\n", __func__, ret);
 373        }
 374#if defined(CONFIG_CMD_PCAP)
 375        if (ret >= 0)
 376                pcap_post(packet, length, true);
 377#endif
 378        return ret;
 379}
 380
 381int eth_rx(void)
 382{
 383        struct udevice *current;
 384        uchar *packet;
 385        int flags;
 386        int ret;
 387        int i;
 388
 389        current = eth_get_dev();
 390        if (!current)
 391                return -ENODEV;
 392
 393        if (!eth_is_active(current))
 394                return -EINVAL;
 395
 396        /* Process up to 32 packets at one time */
 397        flags = ETH_RECV_CHECK_DEVICE;
 398        for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) {
 399                ret = eth_get_ops(current)->recv(current, flags, &packet);
 400                flags = 0;
 401                if (ret > 0)
 402                        net_process_received_packet(packet, ret);
 403                if (ret >= 0 && eth_get_ops(current)->free_pkt)
 404                        eth_get_ops(current)->free_pkt(current, packet, ret);
 405                if (ret <= 0)
 406                        break;
 407        }
 408        if (ret == -EAGAIN)
 409                ret = 0;
 410        if (ret < 0) {
 411                /* We cannot completely return the error at present */
 412                debug("%s: recv() returned error %d\n", __func__, ret);
 413        }
 414        return ret;
 415}
 416
 417int eth_initialize(void)
 418{
 419        int num_devices = 0;
 420        struct udevice *dev;
 421
 422        eth_common_init();
 423
 424        /*
 425         * Devices need to write the hwaddr even if not started so that Linux
 426         * will have access to the hwaddr that u-boot stored for the device.
 427         * This is accomplished by attempting to probe each device and calling
 428         * their write_hwaddr() operation.
 429         */
 430        uclass_first_device_check(UCLASS_ETH, &dev);
 431        if (!dev) {
 432                log_err("No ethernet found.\n");
 433                bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
 434        } else {
 435                char *ethprime = env_get("ethprime");
 436                struct udevice *prime_dev = NULL;
 437
 438                if (ethprime)
 439                        prime_dev = eth_get_dev_by_name(ethprime);
 440                if (prime_dev) {
 441                        eth_set_dev(prime_dev);
 442                        eth_current_changed();
 443                } else {
 444                        eth_set_dev(NULL);
 445                }
 446
 447                bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
 448                do {
 449                        if (device_active(dev)) {
 450                                if (num_devices)
 451                                        printf(", ");
 452
 453                                printf("eth%d: %s", dev_seq(dev), dev->name);
 454
 455                                if (ethprime && dev == prime_dev)
 456                                        printf(" [PRIME]");
 457                        }
 458
 459                        eth_write_hwaddr(dev);
 460
 461                        if (device_active(dev))
 462                                num_devices++;
 463                        uclass_next_device_check(&dev);
 464                } while (dev);
 465
 466                if (!num_devices)
 467                        log_err("No ethernet found.\n");
 468                putc('\n');
 469        }
 470
 471        return num_devices;
 472}
 473
 474static int eth_post_bind(struct udevice *dev)
 475{
 476        if (strchr(dev->name, ' ')) {
 477                printf("\nError: eth device name \"%s\" has a space!\n",
 478                       dev->name);
 479                return -EINVAL;
 480        }
 481
 482#ifdef CONFIG_DM_ETH_PHY
 483        eth_phy_binds_nodes(dev);
 484#endif
 485
 486        return 0;
 487}
 488
 489static int eth_pre_unbind(struct udevice *dev)
 490{
 491        /* Don't hang onto a pointer that is going away */
 492        if (dev == eth_get_uclass_priv()->current)
 493                eth_set_dev(NULL);
 494
 495        return 0;
 496}
 497
 498static bool eth_dev_get_mac_address(struct udevice *dev, u8 mac[ARP_HLEN])
 499{
 500#if CONFIG_IS_ENABLED(OF_CONTROL)
 501        const uint8_t *p;
 502
 503        p = dev_read_u8_array_ptr(dev, "mac-address", ARP_HLEN);
 504        if (!p)
 505                p = dev_read_u8_array_ptr(dev, "local-mac-address", ARP_HLEN);
 506
 507        if (!p)
 508                return false;
 509
 510        memcpy(mac, p, ARP_HLEN);
 511
 512        return true;
 513#else
 514        return false;
 515#endif
 516}
 517
 518static int eth_post_probe(struct udevice *dev)
 519{
 520        struct eth_device_priv *priv = dev_get_uclass_priv(dev);
 521        struct eth_pdata *pdata = dev_get_plat(dev);
 522        unsigned char env_enetaddr[ARP_HLEN];
 523        char *source = "DT";
 524
 525#if defined(CONFIG_NEEDS_MANUAL_RELOC)
 526        struct eth_ops *ops = eth_get_ops(dev);
 527        static int reloc_done;
 528
 529        if (!reloc_done) {
 530                if (ops->start)
 531                        ops->start += gd->reloc_off;
 532                if (ops->send)
 533                        ops->send += gd->reloc_off;
 534                if (ops->recv)
 535                        ops->recv += gd->reloc_off;
 536                if (ops->free_pkt)
 537                        ops->free_pkt += gd->reloc_off;
 538                if (ops->stop)
 539                        ops->stop += gd->reloc_off;
 540                if (ops->mcast)
 541                        ops->mcast += gd->reloc_off;
 542                if (ops->write_hwaddr)
 543                        ops->write_hwaddr += gd->reloc_off;
 544                if (ops->read_rom_hwaddr)
 545                        ops->read_rom_hwaddr += gd->reloc_off;
 546
 547                reloc_done++;
 548        }
 549#endif
 550
 551        priv->state = ETH_STATE_INIT;
 552        priv->running = false;
 553
 554        /* Check if the device has a valid MAC address in device tree */
 555        if (!eth_dev_get_mac_address(dev, pdata->enetaddr) ||
 556            !is_valid_ethaddr(pdata->enetaddr)) {
 557                source = "ROM";
 558                /* Check if the device has a MAC address in ROM */
 559                if (eth_get_ops(dev)->read_rom_hwaddr)
 560                        eth_get_ops(dev)->read_rom_hwaddr(dev);
 561        }
 562
 563        eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
 564        if (!is_zero_ethaddr(env_enetaddr)) {
 565                if (!is_zero_ethaddr(pdata->enetaddr) &&
 566                    memcmp(pdata->enetaddr, env_enetaddr, ARP_HLEN)) {
 567                        printf("\nWarning: %s MAC addresses don't match:\n",
 568                               dev->name);
 569                        printf("Address in %s is\t\t%pM\n",
 570                               source, pdata->enetaddr);
 571                        printf("Address in environment is\t%pM\n",
 572                               env_enetaddr);
 573                }
 574
 575                /* Override the ROM MAC address */
 576                memcpy(pdata->enetaddr, env_enetaddr, ARP_HLEN);
 577        } else if (is_valid_ethaddr(pdata->enetaddr)) {
 578                eth_env_set_enetaddr_by_index("eth", dev_seq(dev),
 579                                              pdata->enetaddr);
 580        } else if (is_zero_ethaddr(pdata->enetaddr) ||
 581                   !is_valid_ethaddr(pdata->enetaddr)) {
 582#ifdef CONFIG_NET_RANDOM_ETHADDR
 583                net_random_ethaddr(pdata->enetaddr);
 584                printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
 585                       dev->name, dev_seq(dev), pdata->enetaddr);
 586#else
 587                printf("\nError: %s address not set.\n",
 588                       dev->name);
 589                return -EINVAL;
 590#endif
 591        }
 592
 593        eth_write_hwaddr(dev);
 594
 595        return 0;
 596}
 597
 598static int eth_pre_remove(struct udevice *dev)
 599{
 600        struct eth_pdata *pdata = dev_get_plat(dev);
 601
 602        eth_get_ops(dev)->stop(dev);
 603
 604        /* clear the MAC address */
 605        memset(pdata->enetaddr, 0, ARP_HLEN);
 606
 607        return 0;
 608}
 609
 610UCLASS_DRIVER(ethernet) = {
 611        .name           = "ethernet",
 612        .id             = UCLASS_ETH,
 613        .post_bind      = eth_post_bind,
 614        .pre_unbind     = eth_pre_unbind,
 615        .post_probe     = eth_post_probe,
 616        .pre_remove     = eth_pre_remove,
 617        .priv_auto      = sizeof(struct eth_uclass_priv),
 618        .per_device_auto        = sizeof(struct eth_device_priv),
 619        .flags          = DM_UC_FLAG_SEQ_ALIAS,
 620};
 621